Full 118-element visual periodic table with color-coded categories, arrow navigation, detail view with Estonian names, atomic mass, electron shells, state
# Perioodilisustabel EE - NumWorks # Created by Alvar Laigna - https://alvarlaigna.com # Nooled:liigu OK:vaata 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 SW,SH=320,222 BK=(0,)*3;WH=(255,)*3 BL=(50,110,230);TL=(0,190,190) YL=(220,200,60);GN=(60,190,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) # Category colors: 0=Leelism,1=Leel.muld,2=Siirde,3=Muu met,4=Poolmet,5=Mittmet,6=Halogen,7=Vaarisg,8=Lantan,9=Aktin CC=[(230,80,80),(240,150,50),(255,200,80),(180,180,200), (140,200,140),(80,200,80),(100,220,220),(160,120,220), (255,160,140),(255,130,160),(200,200,80)] # Category names in Estonian CN="Leelismetall,Leelismuldmetall,Siirdemetall,Muu metall,Poolmetallid,Mittemetall,Halogeenid,Vaarisgaas,Lantanoidid,Aktinoidid,Muu mittemetall".split(",") # States: 0=Tahke,1=Vedel,2=Gaas,3=Tundmata SN=("Tahke","Vedel","Gaas","Tundmatu") # Element data: symbol,mass,category,state,shells # Stored as compact string, parsed on demand SY="H,He,Li,Be,B,C,N,O,F,Ne,Na,Mg,Al,Si,P,S,Cl,Ar,K,Ca,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr,Rb,Sr,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I,Xe,Cs,Ba,La,Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu,Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn,Fr,Ra,Ac,Th,Pa,U,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Lr,Rf,Db,Sg,Bh,Hs,Mt,Ds,Rg,Cn,Nh,Fl,Mc,Lv,Ts,Og".split(",") NM="Vesinik,Heelium,Liitium,Berullium,Boor,Susinik,Laammastik,Hapnik,Fluor,Neoon,Naatrium,Magneesium,Alumiinium,Raanium,Fosfor,Vaavel,Kloor,Argoon,Kaalium,Kaltsium,Skandium,Titaan,Vanaadium,Kroom,Mangaan,Raud,Koobalt,Nikkel,Vask,Tsink,Gallium,Germaanium,Arseen,Seleen,Broom,Krupton,Rubiidium,Strontsium,Utrium,Tsirkoonium,Nioobium,Molubdeen,Tehneetsium,Ruteenium,Roodium,Pallaadium,Hobe,Kaadmium,Indium,Tina,Antimon,Telluur,Jood,Ksenoon,Tseesium,Baarium,Lantaan,Tseerium,Praseoduum,Neoduum,Promeetium,Samaarium,Euroopium,Gadoliinium,Terbium,Dusprosium,Holmium,Erbium,Tuulium,Uterbium,Luteetsium,Hafnium,Tantaal,Volfram,Reenium,Osmium,Iriidium,Plaatina,Kuld,Elavhobe,Tallium,Plii,Vismut,Poloonium,Astaat,Radoon,Frantsium,Raadium,Aktiinium,Toorium,Protaktiinium,Uraan,Neptuunium,Plutoonium,Ameriitsium,Kuurium,Berkelium,Kalifornium,Einsteinium,Fermium,Mendeleevium,Nobelium,Lavrentsium,Rutherfordium,Dubnium,Seaborgium,Boorium,Hassium,Meitnerium,Darmstadtium,Rontgenium,Kopernitsium,Nihoonium,Flerovium,Moskovium,Livermorium,Tenessiin,Oganessoon".split(",") # Atomic masses (rounded) MS="1.008,4.003,6.941,9.012,10.81,12.01,14.01,16.00,19.00,20.18,22.99,24.31,26.98,28.09,30.97,32.07,35.45,39.95,39.10,40.08,44.96,47.87,50.94,52.00,54.94,55.85,58.93,58.69,63.55,65.38,69.72,72.63,74.92,78.97,79.90,83.80,85.47,87.62,88.91,91.22,92.91,95.95,98.00,101.1,102.9,106.4,107.9,112.4,114.8,118.7,121.8,127.6,126.9,131.3,132.9,137.3,138.9,140.1,140.9,144.2,145.0,150.4,152.0,157.3,158.9,162.5,164.9,167.3,168.9,173.0,175.0,178.5,180.9,183.8,186.2,190.2,192.2,195.1,197.0,200.6,204.4,207.2,209.0,209.0,210.0,222.0,223.0,226.0,227.0,232.0,231.0,238.0,237.0,244.0,243.0,247.0,247.0,251.0,252.0,257.0,258.0,259.0,266.0,267.0,268.0,269.0,270.0,269.0,278.0,281.0,282.0,285.0,286.0,289.0,290.0,293.0,294.0,294.0".split(",") # Category per element (0-10) CT=[5,7,0,1,4,5,5,5,6,7,0,1,3,4,5,5,6,7,0,1,2,2,2,2,2,2,2,2,2,2,3,4,4,10,6,7,0,1,2,2,2,2,2,2,2,2,2,2,3,3,4,4,6,7,0,1,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,2,2,2,2,2,2,2,2,3,3,3,4,6,7,0,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,2,2,2,2,2,2,2,2,2,3,3,3,3,6,7] # State: 0=solid,1=liquid,2=gas,3=unknown ST=[2,2,0,0,0,0,2,2,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] # Electron shells per element ES="1,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.8.1,2.8.2,2.8.3,2.8.4,2.8.5,2.8.6,2.8.7,2.8.8,2.8.8.1,2.8.8.2,2.8.9.2,2.8.10.2,2.8.11.2,2.8.13.1,2.8.13.2,2.8.14.2,2.8.15.2,2.8.16.2,2.8.18.1,2.8.18.2,2.8.18.3,2.8.18.4,2.8.18.5,2.8.18.6,2.8.18.7,2.8.18.8,2.8.18.8.1,2.8.18.8.2,2.8.18.9.2,2.8.18.10.2,2.8.18.12.1,2.8.18.13.1,2.8.18.13.2,2.8.18.15.1,2.8.18.16.1,2.8.18.18.0,2.8.18.18.1,2.8.18.18.2,2.8.18.18.3,2.8.18.18.4,2.8.18.18.5,2.8.18.18.6,2.8.18.18.7,2.8.18.18.8,2.8.18.18.8.1,2.8.18.18.8.2,2.8.18.18.9.2,2.8.18.19.9.2,2.8.18.21.8.2,2.8.18.22.8.2,2.8.18.23.8.2,2.8.18.24.8.2,2.8.18.25.8.2,2.8.18.25.9.2,2.8.18.27.8.2,2.8.18.28.8.2,2.8.18.29.8.2,2.8.18.30.8.2,2.8.18.31.8.2,2.8.18.32.8.2,2.8.18.32.9.2,2.8.18.32.10.2,2.8.18.32.11.2,2.8.18.32.12.2,2.8.18.32.13.2,2.8.18.32.14.2,2.8.18.32.15.2,2.8.18.32.17.1,2.8.18.32.18.1,2.8.18.32.18.2,2.8.18.32.18.3,2.8.18.32.18.4,2.8.18.32.18.5,2.8.18.32.18.6,2.8.18.32.18.7,2.8.18.32.18.8,2.8.18.32.18.8.1,2.8.18.32.18.8.2,2.8.18.32.18.9.2,2.8.18.32.18.10.2,2.8.18.32.20.9.2,2.8.18.32.21.9.2,2.8.18.32.22.9.2,2.8.18.32.24.8.2,2.8.18.32.25.8.2,2.8.18.32.25.9.2,2.8.18.32.27.8.2,2.8.18.32.28.8.2,2.8.18.32.29.8.2,2.8.18.32.30.8.2,2.8.18.32.31.8.2,2.8.18.32.32.8.2,2.8.18.32.32.9.2,2.8.18.32.32.10.2,2.8.18.32.32.11.2,2.8.18.32.32.12.2,2.8.18.32.32.13.2,2.8.18.32.32.14.2,2.8.18.32.32.15.2,2.8.18.32.32.16.2,2.8.18.32.32.17.2,2.8.18.32.32.18.2,2.8.18.32.32.18.3,2.8.18.32.32.18.4,2.8.18.32.32.18.5,2.8.18.32.32.18.6,2.8.18.32.32.18.7,2.8.18.32.32.18.8".split(",") # Grid position: (col,row) for each element # row0-6=main, row8=lanthanides, row9=actinides _G=[] # Row 0: H,He _G+=[(0,0),(17,0)] # Row 1: Li-Ne _G+=[(0,1),(1,1)]+[(c,1) for c in range(12,18)] # Row 2: Na-Ar _G+=[(0,2),(1,2)]+[(c,2) for c in range(12,18)] # Row 3: K-Kr (full) _G+=[(c,3) for c in range(18)] # Row 4: Rb-Xe (full) _G+=[(c,4) for c in range(18)] # Row 5+8: Cs,Ba, La-Lu(row8), Hf-Rn(row5) _G+=[(0,5),(1,5)] _G+=[(3+j,8) for j in range(15)] _G+=[(3+j,5) for j in range(15)] # Row 6+9: Fr,Ra, Ac-Lr(row9), Rf-Og(row6) _G+=[(0,6),(1,6)] _G+=[(3+j,9) for j in range(15)] _G+=[(3+j,6) for j in range(15)] GP=_G # Build reverse lookup: (col,row)->element index GR={} for i in range(118): GR[GP[i]]=i # Grid drawing constants OX=7;OY=1 CW=17;CH=14 def ypos(r): if r<=6:return OY+r*CH return OY+7*CH+4+(r-8)*CH def dcel(i,hl=False): c,r=GP[i] x=OX+c*CW y=ypos(r) cl=CC[CT[i]] if hl: F(x,y,CW,CH,WH) F(x+1,y+1,CW-2,CH-2,cl) else: F(x,y,CW,CH,cl) s=SY[i] tx=x+1 if len(s)==2 else x+5 D(s,tx,y+1,BK if not hl else WH,cl) def dgrid(): F(0,0,SW,SH,BK) for i in range(118): dcel(i) # Ln/Ac markers D("*",OX+2*CW+3,ypos(5)+1,(200,140,120),BK) D("**",OX+2*CW+1,ypos(6)+1,(200,110,140),BK) D("Ln",OX+3,ypos(8)+1,(200,140,120),BK) D("Ac",OX+3,ypos(9)+1,(200,110,140),BK) def sbar(i): F(0,SH-18,SW,18,(20,20,40)) s=SY[i];n=NM[i];z=str(i+1) t=z+". "+s+" - "+n+" ["+CN[CT[i]]+"]" if len(t)>38:t=t[:38] D(t,4,SH-16,TL,(20,20,40)) def detail(i): bg=(20,20,40) F(0,0,SW,SH,bg) cl=CC[CT[i]] # Header box F(10,5,SW-20,50,cl) z=str(i+1) D(z,16,8,BK,cl) D(SY[i],16,24,(40,40,40),cl) D(NM[i],80,10,BK,cl) D(MS[i]+" u",80,30,BK,cl) # Info lines p=GP[i][1] if p>=8:pr=6 if CT[i]==8 else 7 else:pr=p+1 g=GP[i][0]+1 if CT[i] in (8,9):gs="Ln/Ac" else:gs=str(g) info=[("Aatomnumber",z),("Suumbol",SY[i]), ("Nimetus",NM[i]),("Aatommass",MS[i]+" u"), ("Periood",str(pr)),("Ruhm",gs), ("Kategooria",CN[CT[i]]),("Olek",SN[ST[i]]), ("Elektronkihid",ES[i])] ly=62 for lab,val in info: D(lab+":",10,ly,TL,bg) D(str(val),160,ly,WH,bg) ly+=18 D("Back = tagasi",100,SH-16,DG,bg) while True: if K(17): Z(0.2) return Z(0.03) def legend(): F(0,SH-14,SW,14,BK) def run(): cc,cr=0,0 pi=-1 dgrid() legend() while True: # Find valid element at cursor ei=GR.get((cc,cr),-1) # Draw highlight if ei>=0: if pi>=0 and pi!=ei: dcel(pi) dcel(ei,True) sbar(ei) pi=ei if okp(): if ei>=0: wup() detail(ei) dgrid() legend() if pi>=0: dcel(pi,True) sbar(pi) if K(17): Z(0.2) F(0,0,SW,SH,BK) return nc,nr=cc,cr if K(0):nc=max(0,cc-1);Z(0.12) if K(3):nc=min(17,cc+1);Z(0.12) if K(1): nr=cr-1 if nr<0:nr=0 if nr==7:nr=6 Z(0.12) if K(2): nr=cr+1 if nr>9:nr=9 if nr==7:nr=8 Z(0.12) if (nc,nr)!=(cc,cr): if (nc,nr) in GR: cc,cr=nc,nr else: # Try to find nearest valid cell in new row if nr!=cr: for d in range(18): if (nc+d,nr) in GR: cc,cr=nc+d,nr;break if (nc-d,nr) in GR: cc,cr=nc-d,nr;break elif nc!=cc: cc,cr=nc,nr Z(0.02) run()