chem_ee.py

Created by laigna

Created on March 14, 2026

7.59 KB

Keemia lahendaja molaarmassiga, moolide/massi teisendused, gaasi ruumala normaaltingimustel, lahjendamine (C1V1=C2V2), pH arvutus, massiprotsent ja elemendid.


# Keemia Solver EE - NumWorks
# Created by Alvar Laigna - https://alvarlaigna.com
# Nooled:vali OK:kinnita Back:tagasi
from kandinsky import fill_rect as F,draw_string as D
from ion import keydown as K
from time import sleep as Z
from math import log
SW,SH=320,222
BK=(0,)*3;WH=(255,)*3
BL=(50,110,230);TL=(0,190,190)
YL=(220,200,60);DG=(120,)*3

okv=1 if K(4)or K(52) else 0

def okd():
 return K(4)or K(52)

def okp():
 global okv
 d=okd()
 if d and not okv:
  okv=1
  return True
 if not d:okv=0
 return False

def wup():
 while okd():Z(0.02)
 Z(0.12)

EL={"H":1.008,"He":4.003,"Li":6.941,"Be":9.012,
"B":10.81,"C":12.011,"N":14.007,"O":15.999,
"F":18.998,"Ne":20.18,"Na":22.99,"Mg":24.305,
"Al":26.982,"Si":28.086,"P":30.974,"S":32.065,
"Cl":35.453,"Ar":39.948,"K":39.098,"Ca":40.078,
"Ti":47.867,"Cr":51.996,"Mn":54.938,"Fe":55.845,
"Co":58.933,"Ni":58.693,"Cu":63.546,"Zn":65.38,
"Br":79.904,"Ag":107.87,"Sn":118.71,"I":126.9,
"Ba":137.33,"Au":196.97,"Hg":200.59,"Pb":207.2}

def menu(title,items,sub=False):
 sel=0;n=len(items)
 while True:
  F(0,0,SW,SH,BK)
  D(title,SW//2-len(title)*5,6,TL,BK)
  F(0,24,SW,2,(40,)*3)
  for i in range(n):
   y=34+i*22
   if i==sel:
    F(8,y,SW-16,20,BL)
    D("> "+items[i],14,y+2,WH,BL)
   else:
    D("  "+items[i],14,y+2,DG,BK)
  if sub:D("Back=tagasi",100,SH-16,(60,)*3,BK)
  else:D("Back=valju",115,SH-16,(60,)*3,BK)
  while True:
   if K(1):sel=(sel-1)%n;Z(0.15);break
   if K(2):sel=(sel+1)%n;Z(0.15);break
   if okp():wup();return sel
   if K(17):return-1
   Z(0.04)

def inp(prompt):
 try:return float(input(prompt))
 except:return None

def inps(prompt):
 return input(prompt).strip()

def show(lines):
 F(0,0,SW,SH,BK)
 D("TULEMUS",125,6,TL,BK)
 F(0,24,SW,2,(40,)*3)
 for i,ln in enumerate(lines):
  c=YL if i==len(lines)-1 else WH
  D(str(ln),14,34+i*20,c,BK)
 D("OK=tagasi",120,SH-16,DG,BK)
 while True:
  if okp()or K(17):wup();return
  Z(0.04)

def parse(fm):
 el={};i=0
 while i<len(fm):
  if fm[i].isupper():
   s=fm[i];i+=1
   while i<len(fm) and fm[i].islower():
    s+=fm[i];i+=1
   n=""
   while i<len(fm) and fm[i].isdigit():
    n+=fm[i];i+=1
   n=int(n) if n else 1
   el[s]=el.get(s,0)+n
  else:i+=1
 return el

def molar(fm):
 el=parse(fm);m=0
 for s,n in el.items():
  if s not in EL:return None,s
  m+=EL[s]*n
 return m,None

def f_molar():
 fm=inps("Valem (nt H2O): ")
 if fm:
  m,err=molar(fm)
  if err:show(["Tundmatu element: "+err])
  elif m:
   el=parse(fm)
   r=["Valem: "+fm]
   for s,n in el.items():
    r+=[s+": "+str(n)+"x"+str(EL[s])+"="+str(round(EL[s]*n,3))]
   r+=["M = "+str(round(m,4))+" g/mol"]
   show(r)

def f_moles():
 c=menu("Moolid / Mass",
  ["n = m / M  (leia moolid)",
   "m = n x M  (leia mass)",
   "M = m / n  (leia molaarmass)"],True)
 if c==0:
  m=inp("Mass m (g): ");mm=inp("Molaarmass M (g/mol): ")
  if m is not None and mm and mm!=0:
   show(["n = m / M",
    "m="+str(m)+"g  M="+str(mm)+"g/mol",
    "n = "+str(round(m/mm,6))+" mol"])
 elif c==1:
  n=inp("Moolid n (mol): ");mm=inp("Molaarmass M (g/mol): ")
  if n is not None and mm is not None:
   show(["m = n x M",
    "n="+str(n)+"mol  M="+str(mm)+"g/mol",
    "m = "+str(round(n*mm,6))+" g"])
 elif c==2:
  m=inp("Mass m (g): ");n=inp("Moolid n (mol): ")
  if m is not None and n and n!=0:
   show(["M = m / n",
    "m="+str(m)+"g  n="+str(n)+"mol",
    "M = "+str(round(m/n,4))+" g/mol"])

def f_gas():
 c=menu("Gaas NT (22.4 L/mol)",
  ["V = n x Vm  (leia ruumala)",
   "n = V / Vm  (leia moolid)",
   "Massist (sisesta M)"],True)
 if c==0:
  n=inp("Moolid n (mol): ")
  if n is not None:
   show(["V = n x Vm (NT)",
    "n="+str(n)+" mol  Vm=22.4 L/mol",
    "V = "+str(round(n*22.4,4))+" L"])
 elif c==1:
  v=inp("Ruumala V (L): ")
  if v is not None:
   show(["n = V / Vm (NT)",
    "V="+str(v)+" L  Vm=22.4 L/mol",
    "n = "+str(round(v/22.4,6))+" mol"])
 elif c==2:
  m=inp("Mass m (g): ");mm=inp("Molaarmass M (g/mol): ")
  if m is not None and mm and mm!=0:
   n=m/mm;v=n*22.4
   show(["Gaas massist (NT)",
    "m="+str(m)+"g  M="+str(mm)+"g/mol",
    "n = "+str(round(n,6))+" mol",
    "V = "+str(round(v,4))+" L"])

def f_dilute():
 c=menu("Lahjendamine C1V1=C2V2",
  ["Leia C2 (loplik konts)",
   "Leia V2 (loplik ruumala)",
   "Leia C1 (algne konts)",
   "Leia V1 (algne ruumala)"],True)
 if c==0:
  c1=inp("C1 (mol/L): ");v1=inp("V1 (L): ")
  v2=inp("V2 (L): ")
  if c1 is not None and v1 is not None and v2 and v2!=0:
   show(["C2 = C1*V1/V2",
    "C1="+str(c1)+" V1="+str(v1)+" V2="+str(v2),
    "C2 = "+str(round(c1*v1/v2,6))+" mol/L"])
 elif c==1:
  c1=inp("C1 (mol/L): ");v1=inp("V1 (L): ")
  c2=inp("C2 (mol/L): ")
  if c1 is not None and v1 is not None and c2 and c2!=0:
   show(["V2 = C1*V1/C2",
    "C1="+str(c1)+" V1="+str(v1)+" C2="+str(c2),
    "V2 = "+str(round(c1*v1/c2,6))+" L"])
 elif c==2:
  v1=inp("V1 (L): ");c2=inp("C2 (mol/L): ")
  v2=inp("V2 (L): ")
  if v1 and v1!=0 and c2 is not None and v2 is not None:
   show(["C1 = C2*V2/V1",
    "V1="+str(v1)+" C2="+str(c2)+" V2="+str(v2),
    "C1 = "+str(round(c2*v2/v1,6))+" mol/L"])
 elif c==3:
  c1=inp("C1 (mol/L): ");c2=inp("C2 (mol/L): ")
  v2=inp("V2 (L): ")
  if c1 and c1!=0 and c2 is not None and v2 is not None:
   show(["V1 = C2*V2/C1",
    "C1="+str(c1)+" C2="+str(c2)+" V2="+str(v2),
    "V1 = "+str(round(c2*v2/c1,6))+" L"])

def f_ph():
 c=menu("pH arvutus",
  ["pH [H+]-st",
   "[H+] pH-st",
   "pOH pH-st",
   "pH pOH-st"],True)
 if c==0:
  h=inp("[H+] (mol/L): ")
  if h and h>0:
   ph=-log(h)/log(10)
   show(["pH = -log10[H+]",
    "[H+] = "+str(h)+" mol/L",
    "pH = "+str(round(ph,4)),
    "pOH = "+str(round(14-ph,4))])
 elif c==1:
  ph=inp("pH: ")
  if ph is not None:
   h=10**(-ph)
   show(["[H+] = 10^(-pH)",
    "pH = "+str(ph),
    "[H+] = "+str(h)+" mol/L",
    "pOH = "+str(round(14-ph,4))])
 elif c==2:
  ph=inp("pH: ")
  if ph is not None:
   show(["pOH = 14 - pH",
    "pH = "+str(ph),
    "pOH = "+str(round(14-ph,4))])
 elif c==3:
  poh=inp("pOH: ")
  if poh is not None:
   show(["pH = 14 - pOH",
    "pOH = "+str(poh),
    "pH = "+str(round(14-poh,4))])

def f_masspct():
 c=menu("Massiprotsent",
  ["w% (leia protsent)",
   "Leia aine mass",
   "Leia lahuse mass"],True)
 if c==0:
  ms=inp("Aine mass (g): ");mt=inp("Lahuse mass (g): ")
  if ms is not None and mt and mt!=0:
   show(["w% = m_aine/m_lahus x100",
    "m_aine="+str(ms)+"g",
    "m_lahus="+str(mt)+"g",
    "w = "+str(round(ms/mt*100,4))+" %"])
 elif c==1:
  w=inp("Massiprotsent (w%): ");mt=inp("Lahuse mass (g): ")
  if w is not None and mt is not None:
   show(["m_aine = w%/100 x m_lahus",
    "w="+str(w)+"%  m_lahus="+str(mt)+"g",
    "m_aine = "+str(round(w/100*mt,4))+" g"])
 elif c==2:
  ms=inp("Aine mass (g): ");w=inp("Massiprotsent (w%): ")
  if ms is not None and w and w!=0:
   show(["m_lahus = m_aine/(w%/100)",
    "m_aine="+str(ms)+"g  w="+str(w)+"%",
    "m_lahus = "+str(round(ms/(w/100),4))+" g"])

def f_elem():
 keys=sorted(EL.keys())
 sel=0;n=len(keys);vis=7
 while True:
  F(0,0,SW,SH,BK)
  t="Elemendid ("+str(n)+")"
  D(t,SW//2-len(t)*5,6,TL,BK)
  F(0,24,SW,2,(40,)*3)
  top=max(0,min(sel-vis//2,n-vis))
  for i in range(vis):
   idx=top+i
   if idx>=n:break
   y=34+i*22
   s=keys[idx]
   txt=s+" - "+str(EL[s])+" g/mol"
   if idx==sel:
    F(8,y,SW-16,20,BL)
    D("> "+txt,14,y+2,WH,BL)
   else:
    D("  "+txt,14,y+2,DG,BK)
  D("Back=tagasi",100,SH-16,(60,)*3,BK)
  while True:
   if K(1):sel=(sel-1)%n;Z(0.15);break
   if K(2):sel=(sel+1)%n;Z(0.15);break
   if K(17):return
   Z(0.04)

CATS=["Molaarmass",
 "Moolid / Mass / M",
 "Gaasi ruumala (NT)",
 "Lahjendamine (C1V1=C2V2)",
 "pH arvutus",
 "Massiprotsent",
 "Elemendid"]
FNS=[f_molar,f_moles,f_gas,f_dilute,
 f_ph,f_masspct,f_elem]
def run():
 while True:
  c=menu("Keemia Solver EE",CATS)
  if c<0:return
  FNS[c]()
run()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.