Hey, I have a chem final tomorrow my teacher gave questions to an AI and asked it to make a study guide based on the question and this is the attached one it made. I am the dumbest person in chemistry and I have no clue about anything in this. I want you to go through everything in the study guide and teach me and make me ready for the test tomorrow. my goal is to get 80 in tests. Also keep in mind that I am allowed to have one A4 size paper as cheat sheet to have with me during test
cd /home/daytona/workspace/attachments/c1917670-4af0-466e-9706-58a2ebf9f687 && pโฆ
mkdir -p /home/daytona/workspace/chem-cheatsheet && ls /home/daytona/workspace/cโฆ
~/chem-cheatsheet/make_cheatsheet.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Table, TableStyle,
Spacer, HRFlowable, KeepTogether)
from reportlab.lib.enums import TA_CENTER, TA_LEFT
import os
output_path = "/home/daytona/workspace/chem-cheatsheet/HonorsChem_CheatSheet.pdf"
doc = SimpleDocTemplate(
output_path,
pagesize=A4,
leftMargin=0.7*cm,
rightMargin=0.7*cm,
topMargin=0.6*cm,
bottomMargin=0.6*cm,
)
W, H = A4
# โโ Color palette โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
DARK_BLUE = colors.HexColor("#1a3a5c")
MED_BLUE = colors.HexColor("#2563a8")
LIGHT_BLUE = colors.HexColor("#dbeafe")
ACCENT = colors.HexColor("#e76f00")
PALE_YELLOW = colors.HexColor("#fffbe6")
PALE_GREEN = colors.HexColor("#eafaf1")
PALE_PINK = colors.HexColor("#fdecea")
WHITE = colors.white
LIGHT_GRAY = colors.HexColor("#f0f4f8")
# โโ Base styles โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def sty(name, parent="Normal", **kw):
s = ParagraphStyle(name, parent=getSampleStyleSheet()[parent])
for k, v in kw.items():
setattr(s, k, v)
return s
title_sty = sty("title", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, spaceAfter=1, spaceBefore=1, leading=13)
sec_sty = sty("sec", fontSize=7.5, textColor=DARK_BLUE, fontName="Helvetica-Bold",
alignment=TA_CENTER, spaceAfter=0, spaceBefore=0, leading=9)
body_sty = sty("body", fontSize=6.5, fontName="Helvetica",
spaceAfter=0, spaceBefore=0, leading=8)
bold_sty = sty("bold", fontSize=6.5, fontName="Helvetica-Bold",
spaceAfter=0, spaceBefore=0, leading=8)
formula_sty = sty("formula",fontSize=6.5, fontName="Courier-Bold", textColor=MED_BLUE,
spaceAfter=0, spaceBefore=0, leading=8)
def P(txt, s=body_sty):
return Paragraph(txt, s)
def header_row(label, bg=MED_BLUE):
return [Paragraph(f"<b>{label}</b>", title_sty)]
def section_table(label, content_rows, col_widths, bg=LIGHT_BLUE, hdr_bg=MED_BLUE, rowbg=None):
"""Build a titled section table."""
# header
data = [[Paragraph(f"<b>{label}</b>", title_sty)]] + content_rows
cw = col_widths
ncols = len(col_widths)
style = [
# header
("BACKGROUND", (0,0), (-1,0), hdr_bg),
("SPAN", (0,0), (-1,0)),
("ALIGN", (0,0), (-1,0), "CENTER"),
("TOPPADDING", (0,0), (-1,0), 2),
("BOTTOMPADDING",(0,0),(-1,0),2),
# body
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 6.2),
("LEADING", (0,1), (-1,-1), 7.5),
("TOPPADDING", (0,1), (-1,-1), 1.2),
("BOTTOMPADDING",(0,1),(-1,-1),1.2),
("LEFTPADDING",(0,0), (-1,-1), 2.5),
("RIGHTPADDING",(0,0),(-1,-1),2.5),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, LIGHT_GRAY]),
("BOX", (0,0), (-1,-1), 0.4, MED_BLUE),
("INNERGRID", (0,1), (-1,-1), 0.2, colors.HexColor("#c8d8e8")),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]
if rowbg:
for i, c in enumerate(rowbg, start=1):
if c:
style.append(("BACKGROUND",(0,i),(-1,i),c))
t = Table(data, colWidths=cw)
t.setStyle(TableStyle(style))
return t
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Build content in two columns
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
usable_w = W - 1.4*cm # total usable width
col_w = (usable_w - 3*mm) / 2 # each column (2 cols with small gap)
# helper to combine two blocks side by side
def two_col(left_items, right_items):
left_str = ""
right_str = ""
# We'll use a Table with two columns, each holding a sub-table
L = [left_items] if not isinstance(left_items, list) else left_items
R = [right_items] if not isinstance(right_items, list) else right_items
inner = Table([[L, R]], colWidths=[col_w, col_w])
inner.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1),"TOP"),
("LEFTPADDING", (0,0),(-1,-1),0),
("RIGHTPADDING",(0,0),(-1,-1),0),
("TOPPADDING", (0,0),(-1,-1),0),
("BOTTOMPADDING",(0,0),(-1,-1),0),
]))
return inner
# โโ Spacer shorthand โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
SP = Spacer(1, 1.5*mm)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 1 โ Formulas (left col)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def formulas_block():
rows = [
[P("<b>Photon freq</b>"), P("ฮฝ = c / ฮป (c=3ร10โธ m/s)", formula_sty)],
[P("<b>Photon energy</b>"), P("E = hฮฝ = hc/ฮป (h=6.626ร10โปยณโด)", formula_sty)],
[P("<b>Specific heat</b>"), P("q = m ร c ร ฮT", formula_sty)],
[P("<b>Calorie conv</b>"), P("1 Cal = 4184 J", formula_sty)],
[P("<b>Moles</b>"), P("n = mass / molar mass", formula_sty)],
[P("<b>% composition</b>"), P("% = (elem mass / MM) ร 100", formula_sty)],
[P("<b>% yield</b>"), P("% yield = actual/theoretical ร 100", formula_sty)],
[P("<b>Avogadro</b>"), P("6.02 ร 10ยฒยณ particles/mol", formula_sty)],
]
return section_table("๐ข KEY FORMULAS (Qs 3โ9, 19โ26)", rows,
[col_w*0.38, col_w*0.62], hdr_bg=DARK_BLUE)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 2 โ Polyatomic Ions (right col)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def ions_block():
rows = [
[P("<b>Ion</b>", bold_sty), P("<b>Name</b>", bold_sty), P("<b>Ion</b>", bold_sty), P("<b>Name</b>", bold_sty)],
[P("SOโยฒโป"), P("sulfate"), P("ClOโป"), P("hypochlorite")],
[P("SOโยฒโป"), P("sulfite"), P("ClOโโป"), P("chlorite")],
[P("NOโโป"), P("nitrate"), P("ClOโโป"), P("chlorate")],
[P("NOโโป"), P("nitrite"), P("ClOโโป"), P("perchlorate")],
[P("POโยณโป"), P("phosphate"), P("OHโป"), P("hydroxide")],
[P("NHโโบ"), P("ammonium"), P("COโยฒโป"), P("carbonate")],
]
style_extra = [("BACKGROUND",(0,1),(-1,1), LIGHT_BLUE),
("FONTNAME",(0,1),(-1,1),"Helvetica-Bold")]
cws = [col_w*0.18, col_w*0.32, col_w*0.18, col_w*0.32]
t = section_table("โก POLYATOMIC IONS", rows, cws, hdr_bg=colors.HexColor("#7c3aed"))
return t
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 3 โ Bonding & Geometry (left)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def bonding_block():
rows = [
[P("<b>Ionic</b>"), P("Metal+Nonmetal, eโป transferred, high MP")],
[P("<b>Covalent</b>"), P("Nonmetal+Nonmetal, eโป shared")],
[P("<b>Coord. cov</b>"), P("ONE atom donates BOTH eโป")],
[P("<b>Single</b>"), P("1ฯ, 0ฯ")],
[P("<b>Double</b>"), P("1ฯ, 1ฯ (e.g. CโHโ: 5ฯ 1ฯ)")],
[P("<b>Triple</b>"), P("1ฯ, 2ฯ โ shortest & strongest")],
[P("<b>Nonpolar</b>"), P("Symmetric (SiHโ tetrahedral)")],
[P("<b>Polar</b>"), P("Lone pairs on center (AsHโ,HโS)")],
[P("<b>HOFBrINCl</b>"), P("Diatomic elements: HโOโFโBrโIโNโClโ")],
]
return section_table("๐ BONDING (Qs 32โ40)", rows,
[col_w*0.28, col_w*0.72], hdr_bg=colors.HexColor("#0f766e"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 4 โ Nomenclature (right)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def nomenclature_block():
rows = [
[P("<b>Variable-charge metal</b>"), P("Use Roman numerals: Feโ(SOโ)โ = Iron(III) sulfate")],
[P("<b>Crossover rule</b>"), P("Caยฒโบ+POโยณโป โ Caโ(POโ)โ (cross charges)")],
[P("<b>Hydrate</b>"), P("CompoundโขxHโO e.g. Ba(OH)โโข8HโO")],
[P("<b>Molecular prefixes</b>"), P("mono di tri tetra penta hexa hepta octa")],
[P("<b>Acid -ate ion</b>"), P("-ic acid: HโSOโ = sulfuric acid")],
[P("<b>Acid -ite ion</b>"), P("-ous acid: HโSOโ = sulfurous acid")],
[P("<b>NโHโ</b>"), P("dinitrogen tetrahydride")],
]
return section_table("๐ NOMENCLATURE (Qs 27,35,36,41โ43)", rows,
[col_w*0.33, col_w*0.67], hdr_bg=colors.HexColor("#b45309"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 5 โ Atomic Structure (left)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def atomic_block():
rows = [
[P("<b>Ground state</b>"), P("Lowest energy โ electrons at rest")],
[P("<b>Excited state</b>"), P("Electron absorbed energy โ jumped up")],
[P("<b>Isotopes</b>"), P("Same element, different # neutrons")],
[P("<b>Allotropes</b>"), P("Same element, diff structure (C: diamond/graphite)")],
[P("<b>Alloy</b>"), P("Metal mixture (steel=Fe+C, bronze=Cu+Sn)")],
[P("<b>Fill order</b>"), P("1s 2s 2p 3s 3p <b>4s</b> 3d 4p 5s 4d 5p โฆ", body_sty)],
[P("<b>Ge config</b>"), P("[Ar] 4sยฒ 3dยนโฐ 4pยฒ (Period 4, Group 14)")],
[P("<b>Octet rule</b>"), P("Stable = 8 electrons in outer shell")],
]
return section_table("โ ATOMIC STRUCTURE (Qs 44โ50)", rows,
[col_w*0.28, col_w*0.72], hdr_bg=colors.HexColor("#6d28d9"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 6 โ Mole/Stoich (right)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def mole_block():
rows = [
[P("<b>moles from g</b>"), P("n = mass รท molar mass")],
[P("<b>g from moles</b>"), P("g = mol ร molar mass")],
[P("<b>Empirical formula</b>"), P("% โ g โ รท atomic mass โ รท smallest โ ratio")],
[P("<b>COโ % C</b>"), P("12/44ร100 = 27.3% C")],
[P("<b>FeโOโ MM</b>"), P("2(56)+3(16) = 159.7 g/mol โ 0.82 mol = 131 g")],
[P("<b>Clโ (100 g)</b>"), P("100รท71 = 1.41 mol")],
[P("<b>HโCrOโ MM</b>"), P("2+52+64 = 118 g/mol")],
]
return section_table("๐งฎ MOLE & MOLAR MASS (Qs 19โ26)", rows,
[col_w*0.32, col_w*0.68], hdr_bg=colors.HexColor("#065f46"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 7 โ Reactions & Stoichiometry (left)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def rxn_block():
rows = [
[P("<b>Balancing</b>"), P("SiOโ+4HFโSiFโ+2HโO (HF coeff=4)")],
[P("<b>Precipitate</b>"), P("Solid (s) product from 2 aq solutions, e.g. AgCl(s)")],
[P("<b>Net ionic</b>"), P("Remove spectator ions | Hโบ+OHโปโHโO")],
[P("<b>Neutralization</b>"),P("Acid+BaseโSalt+Water | Ba(OH)โ+2HClโBaClโ+2HโO")],
[P("<b>Stoich steps</b>"), P("1)Balance eq 2)โmol 3)molar ratio 4)โunits")],
[P("<b>Limiting R.</b>"), P("Runs out first โ determines max product")],
[P("<b>% yield</b>"), P("actualรทtheoreticalร100 (always โค100%)")],
[P("<b>Molar ratio</b>"), P("CโHโ+5Oโโ3COโ+4HโO : Oโ:COโ = 5:3")],
]
return section_table("โ REACTIONS & STOICHIOMETRY (Qs 11โ31)", rows,
[col_w*0.28, col_w*0.72], hdr_bg=colors.HexColor("#9f1239"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# SECTION 8 โ Thermo + Kinetics + Equilibrium (right)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def thermo_block():
rows = [
[P("<b>q=mcฮT ex.</b>"), P("30g Al, 20ยฐC rise: 30ร0.9ร20=540 J")],
[P("<b>Always spontaneous</b>"),P("ฮH<0 AND ฮS>0 โ ฮG always negative")],
[P("<b>Collision theory</b>"), P("Must collide + enough energy + right orientation")],
[P("<b>Activated complex</b>"), P("Unstable high-energy intermediate at energy max")],
[P("<b>โTemp</b>"), P("Rate โ (faster particles, more energetic collisions)")],
[P("<b>Catalyst</b>"), P("Rate โ, lowers Ea, does NOT change ฮH")],
[P("<b>Equilibrium</b>"), P("Fwd rate = Rev rate; both still occurring")],
[P("<b>Keq</b>"), P("Valid only at ONE temperature; conc/pressure shift = no Keq change")],
[P("<b>Le Chatelier</b>"), P("Stress โ shifts to relieve it (add reactant โ more product)")],
]
return section_table("๐ก THERMO ยท KINETICS ยท EQUILIBRIUM (Qs 1โ9)", rows,
[col_w*0.28, col_w*0.72], hdr_bg=colors.HexColor("#1e40af"))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TITLE BANNER
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
title_data = [[Paragraph(
"<b>HONORS CHEMISTRY โ FINAL EXAM CHEAT SHEET</b> ยท All 9 Topics ยท Pendleton High School",
ParagraphStyle("tb", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=11)
)]]
title_t = Table(title_data, colWidths=[usable_w])
title_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), DARK_BLUE),
("TOPPADDING", (0,0),(0,0), 3),
("BOTTOMPADDING",(0,0),(0,0),3),
("LEFTPADDING",(0,0),(0,0),4),
("RIGHTPADDING",(0,0),(0,0),4),
("ROUNDEDCORNERS",[3]),
]))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Assemble document
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
story = []
story.append(title_t)
story.append(Spacer(1, 1.5*mm))
# Row 1: Formulas | Polyatomic Ions
story.append(two_col(formulas_block(), ions_block()))
story.append(Spacer(1, 1.5*mm))
# Row 2: Bonding | Nomenclature
story.append(two_col(bonding_block(), nomenclature_block()))
story.append(Spacer(1, 1.5*mm))
# Row 3: Atomic Structure | Mole
story.append(two_col(atomic_block(), mole_block()))
story.append(Spacer(1, 1.5*mm))
# Row 4: Reactions & Stoich | Thermo+Kinetics+Equil
story.append(two_col(rxn_block(), thermo_block()))
doc.build(story)
print(f"โ
Saved to {output_path}")
cd /home/daytona/workspace/chem-cheatsheet && python3 make_cheatsheet.py 2>&1
ls -lh /home/daytona/workspace/chem-cheatsheet/
HonorsChem CheatSheet
PDF Document ยท PDF
| Priority | Topic | Questions on test |
|---|---|---|
| ๐ด 1st | Atomic Structure & Light | Qs 44โ50 (7 Qs) |
| ๐ด 2nd | Mole & Molar Mass | Qs 19โ26 (8 Qs) |
| ๐ 3rd | Stoichiometry | Qs 11โ18 (8 Qs) |
| ๐ 4th | Chemical Bonding | Qs 32โ40 (9 Qs) |
| ๐ก 5th | Nomenclature | Qs 27, 35, 36, 41โ43 |
| ๐ก 6th | Reactions & Equations | Qs 28โ31 |
| ๐ข 7th | Thermochemistry | Qs 7โ9 |
| ๐ข 8th | Kinetics | Qs 3โ6 |
| ๐ข 9th | Equilibrium | Qs 1โ2 |
ok, I have A4 size paper and I have half front cover with periodic table. I want complete cheat sheet that tell me what to do with problem. how to answer questions not just give formula. also I want to do metallic, nonmetallic, charges, etc key on periodic table so take time and make a perfect cheet sheet with ability of pass any student who even doesnot belong to classs
cd /home/daytona/workspace/chem-cheatsheet && python3 -c " from reportlab.lib.paโฆ
~/chem-cheatsheet/cheatsheet_v2.py
"""
Honors Chemistry โ Ultimate Cheat Sheet (2 pages, A4)
Page 1: Periodic Table with full legend
Page 2: Step-by-step problem-solving guide for all 9 exam topics
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm, inch
from reportlab.lib import colors
from reportlab.pdfgen import canvas
from reportlab.platypus import (SimpleDocTemplate, Table, TableStyle,
Paragraph, Spacer, HRFlowable, KeepTogether, PageBreak)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
import math
W, H = A4 # 595.28 x 841.89
OUT = "/home/daytona/workspace/chem-cheatsheet/HonorsChem_UltimateCheatSheet.pdf"
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# COLOUR PALETTE
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
C = {
# element categories
"alkali": colors.HexColor("#ff8a65"), # orange-red
"alkaline": colors.HexColor("#ffcc02"), # yellow
"transition": colors.HexColor("#90caf9"), # light blue
"post_metal": colors.HexColor("#a5d6a7"), # green
"metalloid": colors.HexColor("#ce93d8"), # purple
"nonmetal": colors.HexColor("#fff176"), # bright yellow
"halogen": colors.HexColor("#80deea"), # teal
"noble": colors.HexColor("#ef9a9a"), # pink
"lanthanide": colors.HexColor("#bcaaa4"), # brown-grey
"actinide": colors.HexColor("#b0bec5"), # blue-grey
"unknown": colors.HexColor("#eeeeee"),
# ui
"hdr": colors.HexColor("#1a237e"),
"hdr2": colors.HexColor("#283593"),
"hdr3": colors.HexColor("#1565c0"),
"sec1": colors.HexColor("#0d47a1"),
"sec2": colors.HexColor("#1b5e20"),
"sec3": colors.HexColor("#4a148c"),
"sec4": colors.HexColor("#b71c1c"),
"sec5": colors.HexColor("#e65100"),
"sec6": colors.HexColor("#006064"),
"sec7": colors.HexColor("#880e4f"),
"sec8": colors.HexColor("#33691e"),
"sec9": colors.HexColor("#37474f"),
"step_bg": colors.HexColor("#e8f5e9"),
"warn_bg": colors.HexColor("#fff3e0"),
"tip_bg": colors.HexColor("#e3f2fd"),
"example_bg": colors.HexColor("#fce4ec"),
"white": colors.white,
"light": colors.HexColor("#f5f5f5"),
"border": colors.HexColor("#90a4ae"),
"black": colors.black,
"darktext": colors.HexColor("#212121"),
}
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PERIODIC TABLE DATA
# format: (symbol, atomic_num, category, common_charge)
# category keys match C dict above
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ELEMENTS = {
# period 1
(1,1): ("H", 1, "nonmetal", "1+/1โ"),
(1,18): ("He", 2, "noble", "0"),
# period 2
(2,1): ("Li", 3, "alkali", "1+"),
(2,2): ("Be", 4, "alkaline", "2+"),
(2,13): ("B", 5, "metalloid", "3+"),
(2,14): ("C", 6, "nonmetal", "4โ"),
(2,15): ("N", 7, "nonmetal", "3โ"),
(2,16): ("O", 8, "nonmetal", "2โ"),
(2,17): ("F", 9, "halogen", "1โ"),
(2,18): ("Ne", 10, "noble", "0"),
# period 3
(3,1): ("Na", 11, "alkali", "1+"),
(3,2): ("Mg", 12, "alkaline", "2+"),
(3,13): ("Al", 13, "post_metal","3+"),
(3,14): ("Si", 14, "metalloid", "4โ"),
(3,15): ("P", 15, "nonmetal", "3โ"),
(3,16): ("S", 16, "nonmetal", "2โ"),
(3,17): ("Cl", 17, "halogen", "1โ"),
(3,18): ("Ar", 18, "noble", "0"),
# period 4
(4,1): ("K", 19, "alkali", "1+"),
(4,2): ("Ca", 20, "alkaline", "2+"),
(4,3): ("Sc", 21, "transition","3+"),
(4,4): ("Ti", 22, "transition","4+"),
(4,5): ("V", 23, "transition","var"),
(4,6): ("Cr", 24, "transition","var"),
(4,7): ("Mn", 25, "transition","var"),
(4,8): ("Fe", 26, "transition","var"),
(4,9): ("Co", 27, "transition","var"),
(4,10): ("Ni", 28, "transition","var"),
(4,11): ("Cu", 29, "transition","var"),
(4,12): ("Zn", 30, "transition","2+"),
(4,13): ("Ga", 31, "post_metal","3+"),
(4,14): ("Ge", 32, "metalloid", "4โ"),
(4,15): ("As", 33, "metalloid", "3โ"),
(4,16): ("Se", 34, "nonmetal", "2โ"),
(4,17): ("Br", 35, "halogen", "1โ"),
(4,18): ("Kr", 36, "noble", "0"),
# period 5
(5,1): ("Rb", 37, "alkali", "1+"),
(5,2): ("Sr", 38, "alkaline", "2+"),
(5,3): ("Y", 39, "transition","3+"),
(5,4): ("Zr", 40, "transition","4+"),
(5,5): ("Nb", 41, "transition","var"),
(5,6): ("Mo", 42, "transition","var"),
(5,7): ("Tc", 43, "transition","var"),
(5,8): ("Ru", 44, "transition","var"),
(5,9): ("Rh", 45, "transition","var"),
(5,10): ("Pd", 46, "transition","var"),
(5,11): ("Ag", 47, "transition","1+"),
(5,12): ("Cd", 48, "transition","2+"),
(5,13): ("In", 49, "post_metal","3+"),
(5,14): ("Sn", 50, "post_metal","var"),
(5,15): ("Sb", 51, "metalloid", "3โ"),
(5,16): ("Te", 52, "metalloid", "2โ"),
(5,17): ("I", 53, "halogen", "1โ"),
(5,18): ("Xe", 54, "noble", "0"),
# period 6
(6,1): ("Cs", 55, "alkali", "1+"),
(6,2): ("Ba", 56, "alkaline", "2+"),
(6,3): ("La*",57, "lanthanide","3+"),
(6,4): ("Hf", 72, "transition","4+"),
(6,5): ("Ta", 73, "transition","5+"),
(6,6): ("W", 74, "transition","var"),
(6,7): ("Re", 75, "transition","var"),
(6,8): ("Os", 76, "transition","var"),
(6,9): ("Ir", 77, "transition","var"),
(6,10): ("Pt", 78, "transition","var"),
(6,11): ("Au", 79, "transition","var"),
(6,12): ("Hg", 80, "transition","var"),
(6,13): ("Tl", 81, "post_metal","var"),
(6,14): ("Pb", 82, "post_metal","var"),
(6,15): ("Bi", 83, "post_metal","3+"),
(6,16): ("Po", 84, "metalloid", "2โ"),
(6,17): ("At", 85, "halogen", "1โ"),
(6,18): ("Rn", 86, "noble", "0"),
# period 7
(7,1): ("Fr", 87, "alkali", "1+"),
(7,2): ("Ra", 88, "alkaline", "2+"),
(7,3): ("Ac*",89, "actinide", "3+"),
}
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# DRAW PERIODIC TABLE (Page 1)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def draw_page1(c_obj):
c_obj.setPageSize(A4)
page_w, page_h = A4
margin = 6*mm
# โโ TITLE BAR โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
bar_h = 18
c_obj.setFillColor(C["hdr"])
c_obj.rect(0, page_h - bar_h, page_w, bar_h, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 10)
c_obj.drawCentredString(page_w/2, page_h - 13, "HONORS CHEMISTRY โ ULTIMATE CHEAT SHEET ยท PAGE 1: PERIODIC TABLE REFERENCE")
# โโ Table area โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
top = page_h - bar_h - 3*mm
table_area_h = page_h * 0.50 # upper half
legend_area_h = page_h * 0.47 # lower half
# How many rows/cols: 7 rows (periods) + 2 gap rows for lanthanides/actinides
# 18 columns (groups)
num_rows = 9 # 7 periods + blank + 2 lan/act rows
num_cols = 18
cell_w = (page_w - 2*margin) / num_cols
cell_h = table_area_h / (num_rows + 0.5)
def draw_element(period, group, x_off=0, y_off=0):
key = (period, group)
if key not in ELEMENTS:
return
sym, anum, cat, charge = ELEMENTS[key]
# position: col = group-1, row = period-1
col_idx = group - 1
row_idx = period - 1
x = margin + col_idx * cell_w + x_off
y = top - (row_idx + 1) * cell_h + y_off
bg = C.get(cat, C["unknown"])
c_obj.setFillColor(bg)
c_obj.setStrokeColor(colors.HexColor("#546e7a"))
c_obj.setLineWidth(0.3)
c_obj.rect(x, y, cell_w - 0.5, cell_h - 0.5, fill=1, stroke=1)
# atomic number
c_obj.setFillColor(colors.HexColor("#37474f"))
c_obj.setFont("Helvetica", 4.5)
c_obj.drawString(x + 1, y + cell_h - 6, str(anum))
# symbol
c_obj.setFillColor(C["black"])
sym_size = 7.5 if len(sym) <= 2 else 6.5
c_obj.setFont("Helvetica-Bold", sym_size)
c_obj.drawCentredString(x + cell_w/2, y + cell_h/2 - 2, sym)
# charge (tiny)
c_obj.setFillColor(colors.HexColor("#b71c1c"))
c_obj.setFont("Helvetica", 3.8)
c_obj.drawCentredString(x + cell_w/2, y + 1.5, charge)
# Draw all elements periods 1-7
for (period, group) in ELEMENTS:
if period <= 7:
draw_element(period, group)
# โโ Lanthanide / Actinide rows (offset below main table) โโโโโโโ
lan_y_offset = -(1.3 * cell_h) # shift down 1.3 rows below row 7
act_y_offset = -(2.0 * cell_h)
lan_symbols = [("La",57,"lanthanide","3+"),("Ce",58,"lanthanide","3+"),
("Pr",59,"lanthanide","3+"),("Nd",60,"lanthanide","3+"),
("Pm",61,"lanthanide","var"),("Sm",62,"lanthanide","3+"),
("Eu",63,"lanthanide","3+"),("Gd",64,"lanthanide","3+"),
("Tb",65,"lanthanide","3+"),("Dy",66,"lanthanide","3+"),
("Ho",67,"lanthanide","3+"),("Er",68,"lanthanide","3+"),
("Tm",69,"lanthanide","3+"),("Yb",70,"lanthanide","2+/3+"),
("Lu",71,"lanthanide","3+")]
act_symbols = [("Ac",89,"actinide","3+"),("Th",90,"actinide","4+"),
("Pa",91,"actinide","5+"),("U",92,"actinide","var"),
("Np",93,"actinide","var"),("Pu",94,"actinide","var"),
("Am",95,"actinide","3+"),("Cm",96,"actinide","3+"),
("Bk",97,"actinide","3+"),("Cf",98,"actinide","3+"),
("Es",99,"actinide","3+"),("Fm",100,"actinide","3+"),
("Md",101,"actinide","3+"),("No",102,"actinide","2+"),
("Lr",103,"actinide","3+")]
for i, (sym, anum, cat, charge) in enumerate(lan_symbols):
col_idx = i + 3 # start at column 4
row_idx = 7 # row 8 (below period 7)
x = margin + col_idx * cell_w
y = top - (row_idx + 1) * cell_h + lan_y_offset
bg = C.get(cat, C["unknown"])
c_obj.setFillColor(bg)
c_obj.setStrokeColor(colors.HexColor("#546e7a"))
c_obj.setLineWidth(0.3)
c_obj.rect(x, y, cell_w - 0.5, cell_h - 0.5, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#37474f"))
c_obj.setFont("Helvetica", 4.5)
c_obj.drawString(x + 1, y + cell_h - 6, str(anum))
c_obj.setFillColor(C["black"])
c_obj.setFont("Helvetica-Bold", 7)
c_obj.drawCentredString(x + cell_w/2, y + cell_h/2 - 2, sym)
c_obj.setFillColor(colors.HexColor("#b71c1c"))
c_obj.setFont("Helvetica", 3.8)
c_obj.drawCentredString(x + cell_w/2, y + 1.5, charge)
for i, (sym, anum, cat, charge) in enumerate(act_symbols):
col_idx = i + 3
row_idx = 8
x = margin + col_idx * cell_w
y = top - (row_idx + 1) * cell_h + act_y_offset
bg = C.get(cat, C["unknown"])
c_obj.setFillColor(bg)
c_obj.setStrokeColor(colors.HexColor("#546e7a"))
c_obj.setLineWidth(0.3)
c_obj.rect(x, y, cell_w - 0.5, cell_h - 0.5, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#37474f"))
c_obj.setFont("Helvetica", 4.5)
c_obj.drawString(x + 1, y + cell_h - 6, str(anum))
c_obj.setFillColor(C["black"])
c_obj.setFont("Helvetica-Bold", 7)
c_obj.drawCentredString(x + cell_w/2, y + cell_h/2 - 2, sym)
c_obj.setFillColor(colors.HexColor("#b71c1c"))
c_obj.setFont("Helvetica", 3.8)
c_obj.drawCentredString(x + cell_w/2, y + 1.5, charge)
# โโ Group labels across top โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
groups = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"]
group_names = ["IA","IIA","","","","","","","","","","","IIIA","IVA","VA","VIA","VIIA","0"]
for i, (g, gn) in enumerate(zip(groups, group_names)):
x = margin + i * cell_w + cell_w/2
y = top + 1*mm
c_obj.setFillColor(C["hdr2"])
c_obj.setFont("Helvetica-Bold", 5.5)
c_obj.drawCentredString(x, y, g)
c_obj.setFillColor(C["sec9"])
c_obj.setFont("Helvetica", 4.5)
c_obj.drawCentredString(x, y - 5, gn)
# โโ Period labels โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
for p in range(1, 8):
y = top - p * cell_h + cell_h/2 - 2
c_obj.setFillColor(C["hdr2"])
c_obj.setFont("Helvetica-Bold", 6)
c_obj.drawRightString(margin - 1, y, str(p))
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# LEGEND AREA (lower half of page)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Calculate where periodic table ends
last_element_y = top - 7 * cell_h + act_y_offset - 2*mm
legend_top = last_element_y - 4*mm
# โโ Legend title โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
c_obj.setFillColor(C["hdr"])
c_obj.rect(margin, legend_top - 10, page_w - 2*margin, 11, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 8)
c_obj.drawCentredString(page_w/2, legend_top - 7, "PERIODIC TABLE KEY โ Everything you need to read and use the table above")
legend_y = legend_top - 14
# โโ Category legend โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
cats = [
("Alkali Metals\n(Group 1)", "alkali", "Very reactive, 1+ charge\nNa, K, Li, Rb, Cs"),
("Alkaline Earth\n(Group 2)", "alkaline", "Reactive, 2+ charge\nMg, Ca, Ba, Sr"),
("Transition Metals\n(Groups 3โ12)", "transition", "Often variable charge\nFe, Cu, Zn, Cr, Mn"),
("Post-Transition\nMetals", "post_metal", "Lower melting metals\nAl(3+), Pb, Sn"),
("Metalloids", "metalloid", "Semi-metal properties\nSi, Ge, As, B"),
("Nonmetals\n(non-halogens)", "nonmetal", "Form negative ions\nC, N, O, P, S"),
("Halogens\n(Group 17)", "halogen", "Very reactive, 1โ charge\nF, Cl, Br, I"),
("Noble Gases\n(Group 18)", "noble", "Inert, 0 charge\nHe, Ne, Ar"),
]
box_w = (page_w - 2*margin) / 4
box_h = 22
for i, (name, cat, desc) in enumerate(cats):
col = i % 4
row = i // 4
x = margin + col * box_w
y = legend_y - row * (box_h + 1.5)
# color swatch
c_obj.setFillColor(C[cat])
c_obj.setStrokeColor(C["border"])
c_obj.setLineWidth(0.5)
c_obj.rect(x, y - box_h + 2, box_w - 2, box_h - 2, fill=1, stroke=1)
c_obj.setFillColor(C["black"])
c_obj.setFont("Helvetica-Bold", 6.5)
# split name lines
lines = name.split("\n")
for li, ln in enumerate(lines):
c_obj.drawString(x + 2, y - 8 - li*7, ln)
c_obj.setFillColor(colors.HexColor("#37474f"))
c_obj.setFont("Helvetica", 5.5)
desc_lines = desc.split("\n")
for li, ln in enumerate(desc_lines):
c_obj.drawString(x + 2, y - 8 - len(lines)*7 - li*6, ln)
legend_y2 = legend_y - 2*(box_h + 1.5) - 5*mm
# โโ Metal vs Nonmetal dividing line arrow โโโโโโโโโโโโโโโโโโโโโโ
c_obj.setFillColor(C["hdr"])
c_obj.setFont("Helvetica-Bold", 7)
c_obj.drawString(margin, legend_y2, "METALS (left of staircase) vs NONMETALS (right of staircase) vs METALLOIDS (on the staircase line)")
# โโ Group charges quick-ref โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
legend_y3 = legend_y2 - 7*mm
c_obj.setFillColor(C["hdr2"])
c_obj.rect(margin, legend_y3 - 10, page_w - 2*margin, 11, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 7.5)
c_obj.drawCentredString(page_w/2, legend_y3 - 7.5, "COMMON ION CHARGES โ Memorize these!")
charges_table_y = legend_y3 - 14
charge_data = [
("Group 1\n(Li,Na,K,Rb,Cs)", "1+", C["alkali"]),
("Group 2\n(Be,Mg,Ca,Sr,Ba)", "2+", C["alkaline"]),
("Group 13\n(Al,Ga,In)", "3+", C["post_metal"]),
("Group 15\n(N,P,As)", "3โ", C["nonmetal"]),
("Group 16\n(O,S,Se,Te)", "2โ", C["nonmetal"]),
("Group 17\n(F,Cl,Br,I,At)", "1โ", C["halogen"]),
("Group 18\n(He,Ne,Ar,Kr)", "0", C["noble"]),
("Transition metals\n(Fe,Cu,Cr,Mnโฆ)", "VARIABLE\n(Roman #)", C["transition"]),
]
cbox_w = (page_w - 2*margin) / 8
cbox_h = 22
for i, (name, charge, bg) in enumerate(charge_data):
x = margin + i * cbox_w
y_c = charges_table_y
c_obj.setFillColor(bg)
c_obj.setStrokeColor(C["border"])
c_obj.setLineWidth(0.5)
c_obj.rect(x, y_c - cbox_h, cbox_w - 1, cbox_h, fill=1, stroke=1)
c_obj.setFillColor(C["black"])
c_obj.setFont("Helvetica", 5.5)
name_lines = name.split("\n")
for li, ln in enumerate(name_lines):
c_obj.drawCentredString(x + cbox_w/2, y_c - 8 - li*6, ln)
c_obj.setFillColor(C["hdr"])
c_obj.setFont("Helvetica-Bold", 9)
c_obj.drawCentredString(x + cbox_w/2, y_c - cbox_h + 3, charge)
# โโ Special elements box โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
spec_y = charges_table_y - cbox_h - 5*mm
# box background
c_obj.setFillColor(colors.HexColor("#e3f2fd"))
c_obj.setStrokeColor(C["hdr3"])
c_obj.setLineWidth(0.6)
col_w2 = (page_w - 2*margin) / 3
box_height = 30
c_obj.rect(margin, spec_y - box_height, page_w - 2*margin, box_height, fill=1, stroke=1)
# Three special notes side by side
specials = [
("โ
Diatomic Elements (HOFBrINCl)",
"These 7 exist as PAIRS in nature:\nHโ Oโ Fโ Brโ Iโ Nโ Clโ\nAlways write them with subscript 2!"),
("โ
Noble Gases = MONOATOMIC",
"He, Ne, Ar, Kr, Xe, Rn\nGo solo โ never bond with others.\nDo NOT write Heโ!"),
("โ
Variable-Charge Metals (use Roman #)",
"Fe: 2+ (iron II) or 3+ (iron III)\nCu: 1+ (copper I) or 2+ (copper II)\nPb: 2+ or 4+ Sn: 2+ or 4+"),
]
for i, (title, body) in enumerate(specials):
x = margin + i * col_w2 + 2
c_obj.setFillColor(C["hdr"])
c_obj.setFont("Helvetica-Bold", 6.5)
c_obj.drawString(x, spec_y - 9, title)
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
for li, ln in enumerate(body.split("\n")):
c_obj.drawString(x, spec_y - 17 - li*6.5, ln)
# โโ Polyatomic ions โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ions_y = spec_y - box_height - 4*mm
c_obj.setFillColor(colors.HexColor("#4a148c"))
c_obj.rect(margin, ions_y - 10, page_w - 2*margin, 11, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 7.5)
c_obj.drawCentredString(page_w/2, ions_y - 7.5, "POLYATOMIC IONS YOU MUST KNOW (these appear on the exam!)")
ion_y2 = ions_y - 14
ions = [
("SOโยฒโป", "sulfate"), ("SOโยฒโป", "sulfite"),
("NOโโป", "nitrate"), ("NOโโป", "nitrite"),
("POโยณโป", "phosphate"), ("OHโป", "hydroxide"),
("NHโโบ", "ammonium"), ("ClOโป", "hypochlorite"),
("ClOโโป", "chlorite"), ("ClOโโป", "chlorate"),
("ClOโโป", "perchlorate"),("COโยฒโป","carbonate"),
]
ion_col_w = (page_w - 2*margin) / 6
for i, (ion, name) in enumerate(ions):
col = i % 6
row = i // 6
x = margin + col * ion_col_w
y_i = ion_y2 - row * 11
bg_color = colors.HexColor("#ede7f6") if i % 2 == 0 else colors.HexColor("#f3e5f5")
c_obj.setFillColor(bg_color)
c_obj.setStrokeColor(colors.HexColor("#7b1fa2"))
c_obj.setLineWidth(0.4)
c_obj.rect(x, y_i - 9, ion_col_w - 1, 10, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#4a148c"))
c_obj.setFont("Helvetica-Bold", 7)
c_obj.drawString(x + 2, y_i - 7, ion)
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 6)
c_obj.drawString(x + 30, y_i - 7, name)
# โโ Memory tricks โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
mem_y = ion_y2 - 2 * 11 - 3*mm
c_obj.setFillColor(colors.HexColor("#fff8e1"))
c_obj.setStrokeColor(colors.HexColor("#f57f17"))
c_obj.setLineWidth(0.7)
c_obj.rect(margin, mem_y - 24, page_w - 2*margin, 25, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#e65100"))
c_obj.setFont("Helvetica-Bold", 7)
c_obj.drawString(margin + 3, mem_y - 8, "MEMORY TRICKS:")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 6.5)
tricks = (
" -ate = MORE oxygens | -ite = FEWER oxygens (sulfATE=SOโยฒโป has MORE O than sulfITE=SOโยฒโป) "
"| hypo- = fewest O (ClOโป) | per- = most O (ClOโโป) "
"| Electron config fill order: 1s 2s 2p 3s 3p 4s 3d 4p (4s BEFORE 3d!)"
)
c_obj.drawString(margin + 3, mem_y - 18, tricks[:110])
c_obj.drawString(margin + 3, mem_y - 26 + 2, tricks[110:])
# โโ Footer โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
c_obj.setFillColor(C["hdr"])
c_obj.rect(0, 0, page_w, 10, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica", 5.5)
c_obj.drawCentredString(page_w/2, 3, "Page 1 of 2 ยท Pendleton High School ยท Honors Chemistry Final Exam ยท Flip for STEP-BY-STEP PROBLEM SOLVING GUIDE โ")
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PAGE 2 โ STEP-BY-STEP PROBLEM SOLVING GUIDE
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def draw_page2(c_obj):
c_obj.showPage()
c_obj.setPageSize(A4)
page_w, page_h = A4
margin = 6*mm
# TITLE BAR
c_obj.setFillColor(C["hdr"])
c_obj.rect(0, page_h - 18, page_w, 18, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 10)
c_obj.drawCentredString(page_w/2, page_h - 13, "PAGE 2: HOW TO SOLVE EVERY PROBLEM TYPE ยท Step-by-step for ALL 9 exam topics")
y = page_h - 22
col_w = (page_w - 2*margin - 3*mm) / 2
left_x = margin
right_x = margin + col_w + 3*mm
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Helper functions
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def section_bar(x, y, w, title, color):
c_obj.setFillColor(color)
c_obj.rect(x, y - 11, w, 11, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica-Bold", 7.5)
c_obj.drawString(x + 3, y - 8.5, title)
return y - 12
def step_box(x, y, w, steps, bg=colors.HexColor("#e8f5e9"), border=colors.HexColor("#2e7d32")):
"""Draw numbered step box, returns new y"""
line_h = 8
padding = 3
total_h = len(steps) * line_h + 2 * padding
c_obj.setFillColor(bg)
c_obj.setStrokeColor(border)
c_obj.setLineWidth(0.5)
c_obj.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
for i, step in enumerate(steps):
c_obj.setFillColor(border)
c_obj.setFont("Helvetica-Bold", 6)
c_obj.drawString(x + 2, y - padding - i*line_h - 5.5, f"{i+1}.")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 6)
c_obj.drawString(x + 10, y - padding - i*line_h - 5.5, step)
return y - total_h - 1
def example_box(x, y, w, text, bg=colors.HexColor("#fce4ec"), border=colors.HexColor("#c62828")):
lines = text.split("\n")
line_h = 7.5
padding = 3
total_h = len(lines) * line_h + 2 * padding
c_obj.setFillColor(bg)
c_obj.setStrokeColor(border)
c_obj.setLineWidth(0.5)
c_obj.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
c_obj.setFillColor(border)
c_obj.setFont("Helvetica-Bold", 5.5)
c_obj.drawString(x + 2, y - padding - 5, "EXAMPLE:")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
for i, ln in enumerate(lines):
c_obj.drawString(x + 2, y - padding - (i+1)*line_h - 2, ln)
return y - total_h - 1
def tip_box(x, y, w, text, bg=colors.HexColor("#e3f2fd"), border=colors.HexColor("#1565c0")):
lines = text.split("\n")
line_h = 7
padding = 2.5
total_h = len(lines) * line_h + 2 * padding
c_obj.setFillColor(bg)
c_obj.setStrokeColor(border)
c_obj.setLineWidth(0.4)
c_obj.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
c_obj.setFillColor(border)
c_obj.setFont("Helvetica-Bold", 5.5)
c_obj.drawString(x + 2, y - padding - 5, "โ
TIP:")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
for i, ln in enumerate(lines):
c_obj.drawString(x + 30, y - padding - i*line_h - 5, ln)
return y - total_h - 1
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# LEFT COLUMN
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ly = y - 2
# 1. LIGHT & PHOTON ENERGY (Qs 44-50)
ly = section_bar(left_x, ly, col_w, "1. LIGHT & PHOTON ENERGY (Qs 44โ50)", C["sec3"])
ly = step_box(left_x, ly, col_w, [
"Find wavelength (ฮป) or frequency (ฮฝ)? Use: ฮฝ = c / ฮป",
"Find energy (E)? Use: E = h ร ฮฝ",
"c = 3.00ร10โธ m/s h = 6.626ร10โปยณโด Jยทs",
"Watch units! ฮป must be in METERS (convert nm: ร10โปโน)",
])
ly = example_box(left_x, ly, col_w,
"ฮป = 500 nm = 5.00ร10โปโท m\nฮฝ = 3.00ร10โธ / 5.00ร10โปโท = 6.00ร10ยนโด Hz\nE = 6.626ร10โปยณโด ร 6.00ร10ยนโด = 3.98ร10โปยนโน J")
ly -= 1.5*mm
# 2. ELECTRON CONFIGURATION (Qs 44-50)
ly = section_bar(left_x, ly, col_w, "2. ELECTRON CONFIGURATION (Qs 44โ50)", C["sec3"])
ly = step_box(left_x, ly, col_w, [
"Fill in ORDER: 1sยฒ 2sยฒ 2pโถ 3sยฒ 3pโถ 4sยฒ 3dยนโฐ 4pโถ ...",
"USE [noble gas] shortcut: find previous noble gas",
"Then continue filling from where it left off",
"Check: total electrons = atomic number (neutral atom)",
])
ly = example_box(left_x, ly, col_w,
"Germanium (Ge, Z=32, Period 4 Group 14)\nPrev. noble gas = Ar (Z=18) โ [Ar]\nThen add: 4sยฒ 3dยนโฐ 4pยฒ (32-18=14 more eโป)\nFull config: [Ar] 4sยฒ 3dยนโฐ 4pยฒ")
ly -= 1.5*mm
# 3. NAMING IONIC COMPOUNDS
ly = section_bar(left_x, ly, col_w, "3. NAME IONIC COMPOUNDS (Qs 27,41โ43)", C["sec5"])
ly = step_box(left_x, ly, col_w, [
"1st: Write metal name as-is",
"2nd: Is it a variable-charge metal? (Fe,Cu,Pb,Sn,Hg,Cr,Mn...)",
" YES โ figure out charge, add Roman numeral in ()",
" NO โ skip Roman numeral",
"3rd: Write anion name (-ide for simple, -ate/-ite for polyatomic)",
])
ly = example_box(left_x, ly, col_w,
"Feโ(SOโ)โ โ 3 sulfate = 6โ total โ Fe must be 3+ each\nโ Iron(III) sulfate\nCaโ(POโ)โ โ Ca is always 2+, no Roman numeral\nโ Calcium phosphate")
ly -= 1.5*mm
# 4. WRITING IONIC FORMULAS
ly = section_bar(left_x, ly, col_w, "4. WRITE IONIC FORMULAS (Qs 35โ36)", C["sec5"])
ly = step_box(left_x, ly, col_w, [
"Write cation (metal, +) first, anion (nonmetal, โ) second",
"CROSSOVER: swap the charge numbers as subscripts",
"Reduce if possible (e.g. Caยฒโบ + Oยฒโป โ CaO, not CaโOโ)",
"Polyatomic ion with subscript >1? Put it in parentheses",
])
ly = example_box(left_x, ly, col_w,
"Caยฒโบ + POโยณโป โ cross: Caโ(POโ)โ\n Check: 3ร(2+) = 6+ and 2ร(3โ) = 6โ โ\nFeยณโบ + Oยฒโป โ FeโOโ (cross 3 and 2)")
ly -= 1.5*mm
# 5. MOLE CALCULATIONS
ly = section_bar(left_x, ly, col_w, "5. MOLE CALCULATIONS (Qs 19โ26)", C["sec2"])
ly = step_box(left_x, ly, col_w, [
"FIND MOLAR MASS FIRST: add atomic masses of all atoms",
"Grams โ Moles: moles = grams รท molar mass",
"Moles โ Grams: grams = moles ร molar mass",
"Moles โ Particles: particles = moles ร 6.02ร10ยฒยณ",
"Particles โ Moles: moles = particles รท 6.02ร10ยฒยณ",
])
ly = example_box(left_x, ly, col_w,
"How many moles in 100 g Clโ?\n MM of Clโ = 2 ร 35.5 = 71.0 g/mol\n moles = 100 รท 71.0 = 1.41 mol\nMM of HโCrOโ = 2(1) + 52 + 4(16) = 118 g/mol")
ly -= 1.5*mm
# 6. PERCENT COMPOSITION
ly = section_bar(left_x, ly, col_w, "6. PERCENT COMPOSITION (Qs 19โ26)", C["sec2"])
ly = step_box(left_x, ly, col_w, [
"Calculate molar mass of the compound",
"For each element: % = (elem. mass in formula / MM) ร 100",
"All percentages must add to 100%",
])
ly = example_box(left_x, ly, col_w,
"% C in COโ? MM=44 g/mol\n % C = 12/44 ร 100 = 27.3%\n % O = 32/44 ร 100 = 72.7% โ (27.3+72.7=100)")
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# RIGHT COLUMN
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = y - 2
# 7. EMPIRICAL FORMULA
ry = section_bar(right_x, ry, col_w, "7. EMPIRICAL FORMULA FROM % COMP (Qs 19โ26)", C["sec2"])
ry = step_box(right_x, ry, col_w, [
"Assume 100 g sample โ % directly becomes grams",
"Divide each element's grams by its atomic mass โ moles",
"Divide ALL mole values by the SMALLEST one",
"Round to nearest whole number โ those are subscripts",
"If .5 remains, multiply all by 2; if .33, multiply by 3",
])
ry = example_box(right_x, ry, col_w,
"85.6% C, 14.4% H\n C: 85.6 รท 12 = 7.13 mol\n H: 14.4 รท 1 = 14.4 mol\n Divide by smallest (7.13): C=1, H=2.02โ2\n Empirical formula: CHโ")
ry -= 1.5*mm
# 8. STOICHIOMETRY (Qs 11-18)
ry = section_bar(right_x, ry, col_w, "8. STOICHIOMETRY (Qs 11โ18)", C["sec4"])
ry = step_box(right_x, ry, col_w, [
"STEP 1: Write and BALANCE the equation (never skip!)",
"STEP 2: Convert what you're given to MOLES",
" (grams รท molar mass)",
"STEP 3: Multiply by the MOLAR RATIO from equation",
" (coefficient wanted / coefficient given)",
"STEP 4: Convert moles to what they ask for",
" (ร molar mass for grams; ร 6.02ร10ยฒยณ for particles)",
])
ry = example_box(right_x, ry, col_w,
"CโHโ + 5Oโ โ 3COโ + 4HโO\nHow many mol COโ from 2 mol CโHโ?\n ratio COโ:CโHโ = 3:1\n 2 mol CโHโ ร (3/1) = 6 mol COโ")
ry -= 1.5*mm
# 9. LIMITING REACTANT
ry = section_bar(right_x, ry, col_w, "9. LIMITING REACTANT (Qs 11โ18)", C["sec4"])
ry = step_box(right_x, ry, col_w, [
"Balance the equation",
"Convert BOTH reactants to moles",
"Use molar ratio โ find how much product each reactant makes",
"The one that makes LESS product = LIMITING reactant",
"Use limiting reactant's amount to find theoretical yield",
])
ry = example_box(right_x, ry, col_w,
"5 mol Fe + 4 mol Oโ โ 2FeโOโ?\n Balanced: 4Fe + 3Oโ โ 2FeโOโ\n Fe: 5 ร (2/4) = 2.5 mol product\n Oโ: 4 ร (2/3) = 2.67 mol product\n Fe makes less โ Fe is LIMITING REACTANT")
ry -= 1.5*mm
# 10. PERCENT YIELD
ry = section_bar(right_x, ry, col_w, "10. PERCENT YIELD (Qs 11โ18)", C["sec4"])
ry = step_box(right_x, ry, col_w, [
"Theoretical yield = what stoichiometry PREDICTS (max possible)",
"Actual yield = what you ACTUALLY got in the lab",
"% yield = (actual รท theoretical) ร 100",
"% yield is ALWAYS โค 100% (can't make more than predicted!)",
])
ry = example_box(right_x, ry, col_w,
"Theory says 10 g, lab gives 8.2 g\n% yield = (8.2 / 10) ร 100 = 82%")
ry -= 1.5*mm
# 11. THERMOCHEMISTRY
ry = section_bar(right_x, ry, col_w, "11. HEAT & SPONTANEITY (Qs 7โ9)", C["sec6"])
ry = step_box(right_x, ry, col_w, [
"HEAT: q = m ร c ร ฮT (ฮT = T_final โ T_initial)",
"c for water = 4.18 J/gยทยฐC c for Al = 0.900 J/gยทยฐC",
"CALORIES: 1 Cal (food) = 1 kcal = 4184 J",
"SPONTANEOUS if: ฮH<0 AND ฮS>0 (always, any temp)",
"Catalyst: lowers Ea, DOES NOT change ฮH",
])
ry = example_box(right_x, ry, col_w,
"30 g Al heated 20ยฐCโ40ยฐC:\n q = 30 ร 0.900 ร (40โ20) = 540 J\n170 Calories to J:\n 170 ร 4184 = 711,280 J = 7.11ร10โต J")
ry -= 1.5*mm
# 12. KINETICS + EQUILIBRIUM
ry = section_bar(right_x, ry, col_w, "12. KINETICS & EQUILIBRIUM (Qs 1โ6)", C["sec7"])
ry = step_box(right_x, ry, col_w, [
"Rate INCREASES with: โtemp, โconc, โsurface area, catalyst",
"Activated complex = unstable high-E intermediate (not prod, not react)",
"EQUILIBRIUM: forward rate = reverse rate (both still running!)",
"Keq changes ONLY with temperature",
"Le Chatelier: add reactant โ shift right (โ more product)",
"Le Chatelier: add product โ shift left (โ more reactant)",
])
ry = tip_box(right_x, ry, col_w,
"Conc/pressure changes SHIFT equilibrium but DO NOT change Keq value!\nOnly temperature changes Keq itself.")
# โโ BALANCING & NET IONIC (across bottom, full width) โโโโโโโโโโ
bottom_y = min(ly, ry) - 3*mm
full_w = page_w - 2*margin
bottom_y = section_bar(left_x, bottom_y, full_w, "13. BALANCING EQUATIONS & NET IONIC (Qs 28โ31)", C["sec9"])
# two sub-columns
sub_w = (full_w - 2*mm) / 2
# balance steps
balance_steps = [
"Count atoms of each element on each side",
"Add COEFFICIENTS (big numbers in front) to balance",
"NEVER change subscripts inside formulas",
"Balance in this order: metals first, then nonmetals, H last, O last",
]
for i, s in enumerate(balance_steps):
c_obj.setFillColor(colors.HexColor("#e8f5e9"))
c_obj.setStrokeColor(colors.HexColor("#2e7d32"))
c_obj.setLineWidth(0.3)
# left balance box
bx = left_x
by = bottom_y - 1
bh = len(balance_steps) * 8 + 6
c_obj.setFillColor(colors.HexColor("#e8f5e9"))
c_obj.setStrokeColor(colors.HexColor("#2e7d32"))
c_obj.setLineWidth(0.5)
c_obj.rect(bx, by - bh, sub_w, bh, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#1b5e20"))
c_obj.setFont("Helvetica-Bold", 6)
c_obj.drawString(bx+2, by-7, "HOW TO BALANCE:")
for i, s in enumerate(balance_steps):
c_obj.setFillColor(colors.HexColor("#1b5e20"))
c_obj.setFont("Helvetica-Bold", 5.8)
c_obj.drawString(bx+2, by - 15 - i*8, f"{i+1}.")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
c_obj.drawString(bx+10, by - 15 - i*8, s)
# example
ex_y = by - bh - 1
ex_text = ["EX: SiOโ + HF โ SiFโ + HโO",
"Need 4F on right โ 4HF on left",
"4HF โ 4H โ 2HโO โ 2O matches SiOโ โ",
"Answer: SiOโ + 4HF โ SiFโ + 2HโO"]
ex_h = len(ex_text)*7 + 4
c_obj.setFillColor(colors.HexColor("#fce4ec"))
c_obj.setStrokeColor(colors.HexColor("#c62828"))
c_obj.setLineWidth(0.4)
c_obj.rect(bx, ex_y - ex_h, sub_w, ex_h, fill=1, stroke=1)
for i, ln in enumerate(ex_text):
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
c_obj.drawString(bx+3, ex_y - 7 - i*7, ln)
# right: net ionic
nx = left_x + sub_w + 2
ny = bottom_y - 1
net_steps = [
"Write FULL equation with all compounds",
"Split ALL aqueous (aq) ionic compounds into their ions",
"Solids (s), liquids (l), gases (g) stay as molecules",
"Cross out ions that appear UNCHANGED on both sides (spectators)",
"What remains = NET ionic equation",
]
nh = len(net_steps) * 8 + 6
c_obj.setFillColor(colors.HexColor("#e3f2fd"))
c_obj.setStrokeColor(colors.HexColor("#1565c0"))
c_obj.setLineWidth(0.5)
c_obj.rect(nx, ny - nh, sub_w, nh, fill=1, stroke=1)
c_obj.setFillColor(colors.HexColor("#0d47a1"))
c_obj.setFont("Helvetica-Bold", 6)
c_obj.drawString(nx+2, ny-7, "NET IONIC EQUATION:")
for i, s in enumerate(net_steps):
c_obj.setFillColor(colors.HexColor("#0d47a1"))
c_obj.setFont("Helvetica-Bold", 5.8)
c_obj.drawString(nx+2, ny - 15 - i*8, f"{i+1}.")
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
c_obj.drawString(nx+10, ny - 15 - i*8, s)
nex_y = ny - nh - 1
nex = ["HCl(aq)+KOH(aq)โKCl(aq)+HโO(l)",
"Split: Hโบ+Clโป+Kโบ+OHโปโKโบ+Clโป+HโO",
"Spectators: Kโบ and Clโป (cancel them)",
"Net ionic: Hโบ(aq) + OHโป(aq) โ HโO(l)"]
nex_h = len(nex)*7 + 4
c_obj.setFillColor(colors.HexColor("#fce4ec"))
c_obj.setStrokeColor(colors.HexColor("#c62828"))
c_obj.setLineWidth(0.4)
c_obj.rect(nx, nex_y - nex_h, sub_w, nex_h, fill=1, stroke=1)
for i, ln in enumerate(nex):
c_obj.setFillColor(C["darktext"])
c_obj.setFont("Helvetica", 5.8)
c_obj.drawString(nx+3, nex_y - 7 - i*7, ln)
# FOOTER
c_obj.setFillColor(C["hdr"])
c_obj.rect(0, 0, page_w, 10, fill=1, stroke=0)
c_obj.setFillColor(C["white"])
c_obj.setFont("Helvetica", 5.5)
c_obj.drawCentredString(page_w/2, 3, "Page 2 of 2 ยท Pendleton High School ยท Honors Chemistry Final Exam ยท โ See Page 1 for Periodic Table")
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# BUILD PDF
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
c_obj = canvas.Canvas(OUT, pagesize=A4)
draw_page1(c_obj)
draw_page2(c_obj)
c_obj.save()
print(f"โ
Saved: {OUT}")
cd /home/daytona/workspace/chem-cheatsheet && python3 cheatsheet_v2.py 2>&1
ls -lh /home/daytona/workspace/chem-cheatsheet/HonorsChem_UltimateCheatSheet.pdf
HonorsChem UltimateCheatSheet
PDF Document ยท PDF
this is good but I want something that has everything from both the study guide you provide means theory and how to do. also give example but I am not putting them on cheat sheet
~/chem-cheatsheet/studyguide_complete.py
"""
Honors Chemistry โ Complete Study Guide PDF
Full theory + how-to steps + worked examples for all 9 topics
Uses reportlab canvas for full layout control
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.pdfgen import canvas as pdfcanvas
from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER
W, H = A4
OUT = "/home/daytona/workspace/chem-cheatsheet/HonorsChem_StudyGuide_Complete.pdf"
# โโ Colours โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
BG_TITLE = colors.HexColor("#1a237e")
BG_TOPIC = colors.HexColor("#1565c0")
BG_THEORY = colors.HexColor("#e3f2fd")
BG_HOWTO = colors.HexColor("#e8f5e9")
BG_EXAMPLE = colors.HexColor("#fff3e0")
BG_WARN = colors.HexColor("#fce4ec")
BG_PAGE = colors.HexColor("#fafafa")
CLR_THEORY = colors.HexColor("#0d47a1")
CLR_HOWTO = colors.HexColor("#1b5e20")
CLR_EX = colors.HexColor("#e65100")
CLR_WARN = colors.HexColor("#b71c1c")
BLACK = colors.black
GREY = colors.HexColor("#37474f")
WHITE = colors.white
DIVIDER = colors.HexColor("#90a4ae")
MARGIN = 14*mm
COL_GAP = 5*mm
COL_W = (W - 2*MARGIN - COL_GAP) / 2
class PageMaker:
def __init__(self, filename):
self.c = pdfcanvas.Canvas(filename, pagesize=A4)
self.page_num = 0
self._new_page()
def _new_page(self):
self.page_num += 1
self.c.setPageSize(A4)
# light background
self.c.setFillColor(BG_PAGE)
self.c.rect(0, 0, W, H, fill=1, stroke=0)
# footer
self.c.setFillColor(BG_TITLE)
self.c.rect(0, 0, W, 11, fill=1, stroke=0)
self.c.setFillColor(WHITE)
self.c.setFont("Helvetica", 5.5)
self.c.drawCentredString(W/2, 3.5,
f"Honors Chemistry Final Exam โ Complete Study Guide ยท Page {self.page_num} ยท Pendleton High School")
def new_page(self):
self.c.showPage()
self._new_page()
def save(self):
self.c.save()
print(f"โ
Saved: {OUT}")
# โโ Drawing helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def title_bar(pm, y, text, sub=""):
c = pm.c
bar_h = 22 if sub else 16
c.setFillColor(BG_TITLE)
c.rect(0, y - bar_h, W, bar_h, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 12 if sub else 10)
c.drawCentredString(W/2, y - 13, text)
if sub:
c.setFont("Helvetica", 8)
c.drawCentredString(W/2, y - 20, sub)
return y - bar_h - 3*mm
def topic_header(pm, x, y, w, num, title, qs, color=BG_TOPIC):
c = pm.c
c.setFillColor(color)
c.roundRect(x, y - 14, w, 14, 3, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 8.5)
c.drawString(x + 4, y - 10.5, f"TOPIC {num}: {title}")
c.setFont("Helvetica", 7)
c.drawRightString(x + w - 4, y - 10.5, f"Exam: {qs}")
return y - 15
def section_label(pm, x, y, w, label, bg, fg):
c = pm.c
c.setFillColor(bg)
c.rect(x, y - 10, w, 10, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 6.5)
c.drawString(x + 3, y - 7.5, label)
return y - 10
def text_block(pm, x, y, w, lines, font="Helvetica", size=6.8, color=BLACK,
bg=None, border=None, line_h=9, padding_x=4, padding_y=3):
"""Draw a block of text lines with optional background box. Returns new y."""
c = pm.c
total_h = len(lines) * line_h + 2 * padding_y
if bg:
c.setFillColor(bg)
lw = 0.4 if border else 0
if border:
c.setStrokeColor(border)
c.setLineWidth(lw)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1 if border else 0)
c.setFillColor(color)
c.setFont(font, size)
for i, line in enumerate(lines):
# bold prefix support: lines starting with "โข " get normal treatment
c.drawString(x + padding_x, y - padding_y - i * line_h - size + 1, line)
return y - total_h - 1.5*mm
def bullet_block(pm, x, y, w, items, bg=None, border=None,
size=6.8, line_h=9, padding_x=4, padding_y=3):
"""Bullet list with optional box."""
c = pm.c
total_h = len(items) * line_h + 2 * padding_y
if bg:
c.setFillColor(bg)
if border:
c.setStrokeColor(border)
c.setLineWidth(0.4)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1 if border else 0)
for i, item in enumerate(items):
c.setFillColor(CLR_HOWTO if bg == BG_HOWTO else GREY)
c.setFont("Helvetica-Bold", size)
c.drawString(x + padding_x, y - padding_y - i * line_h - size + 1, "โ")
c.setFillColor(BLACK)
c.setFont("Helvetica", size)
c.drawString(x + padding_x + 10, y - padding_y - i * line_h - size + 1, item)
return y - total_h - 1.5*mm
def steps_block(pm, x, y, w, steps, bg=BG_HOWTO, border_color=CLR_HOWTO,
size=6.8, line_h=9):
"""Numbered steps block."""
c = pm.c
padding_x, padding_y = 4, 3
total_h = len(steps) * line_h + 2 * padding_y
c.setFillColor(bg)
c.setStrokeColor(border_color)
c.setLineWidth(0.5)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
for i, step in enumerate(steps):
c.setFillColor(border_color)
c.setFont("Helvetica-Bold", size)
c.drawString(x + padding_x, y - padding_y - i * line_h - size + 1, f"Step {i+1}.")
c.setFillColor(BLACK)
c.setFont("Helvetica", size)
c.drawString(x + padding_x + 32, y - padding_y - i * line_h - size + 1, step)
return y - total_h - 1.5*mm
def example_block(pm, x, y, w, lines, title="WORKED EXAMPLE"):
"""Orange example box."""
c = pm.c
size = 6.8
line_h = 8.5
padding_x, padding_y = 4, 3
total_h = (len(lines) + 1) * line_h + 2 * padding_y
c.setFillColor(BG_EXAMPLE)
c.setStrokeColor(CLR_EX)
c.setLineWidth(0.6)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
c.setFillColor(CLR_EX)
c.setFont("Helvetica-Bold", 6.5)
c.drawString(x + padding_x, y - padding_y - size + 1, f"โ {title}")
c.setFillColor(GREY)
c.setFont("Helvetica", size)
for i, line in enumerate(lines):
c.drawString(x + padding_x + 4, y - padding_y - (i+1) * line_h - size + 1, line)
return y - total_h - 1.5*mm
def warn_box(pm, x, y, w, lines):
"""Red warning/tip box."""
c = pm.c
size = 6.8
line_h = 8.5
padding_x, padding_y = 4, 3
total_h = len(lines) * line_h + 2 * padding_y
c.setFillColor(BG_WARN)
c.setStrokeColor(CLR_WARN)
c.setLineWidth(0.6)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
c.setFillColor(CLR_WARN)
c.setFont("Helvetica-Bold", 6.5)
c.drawString(x + padding_x, y - padding_y - size + 1, "โ REMEMBER:")
c.setFont("Helvetica", size)
for i, line in enumerate(lines):
c.drawString(x + padding_x + 52, y - padding_y - i * line_h - size + 1, line)
return y - total_h - 1.5*mm
def table_block(pm, x, y, w, headers, rows, col_ratios=None, size=6.5, line_h=8.5):
"""Simple table."""
c = pm.c
ncols = len(headers)
if col_ratios is None:
col_ratios = [1/ncols] * ncols
col_widths = [w * r for r in col_ratios]
row_h = line_h + 2
total_h = row_h * (len(rows) + 1)
# header row
cx = x
c.setFillColor(BG_TOPIC)
c.rect(x, y - row_h, w, row_h, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", size)
for h, cw in zip(headers, col_widths):
c.drawString(cx + 3, y - row_h + 3, h)
cx += cw
# data rows
for ri, row in enumerate(rows):
row_y = y - row_h * (ri + 2)
bg = colors.HexColor("#eceff1") if ri % 2 == 0 else WHITE
c.setFillColor(bg)
c.rect(x, row_y, w, row_h, fill=1, stroke=0)
c.setStrokeColor(DIVIDER)
c.setLineWidth(0.2)
c.line(x, row_y, x + w, row_y)
cx = x
c.setFillColor(BLACK)
c.setFont("Helvetica", size)
for cell, cw in zip(row, col_widths):
c.drawString(cx + 3, row_y + 3, str(cell))
cx += cw
# outer border
c.setStrokeColor(BG_TOPIC)
c.setLineWidth(0.5)
c.rect(x, y - total_h, w, total_h, fill=0, stroke=1)
return y - total_h - 1.5*mm
def divider(pm, x, y, w):
pm.c.setStrokeColor(DIVIDER)
pm.c.setLineWidth(0.4)
pm.c.line(x, y, x + w, y)
return y - 2*mm
def gap(y, n=1):
return y - n * 2*mm
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# BUILD THE DOCUMENT
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm = PageMaker(OUT)
c = pm.c
# โโ COVER / TITLE PAGE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = H - 15*mm
c.setFillColor(BG_TITLE)
c.rect(0, y - 60, W, 60, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 20)
c.drawCentredString(W/2, y - 25, "HONORS CHEMISTRY")
c.setFont("Helvetica-Bold", 14)
c.drawCentredString(W/2, y - 40, "FINAL EXAM โ COMPLETE STUDY GUIDE")
c.setFont("Helvetica", 9)
c.drawCentredString(W/2, y - 52, "Theory ยท How to Solve ยท Worked Examples ยท All 9 Exam Topics ยท Pendleton High School")
y -= 68
# intro box
c.setFillColor(colors.HexColor("#e8eaf6"))
c.setStrokeColor(BG_TITLE)
c.setLineWidth(0.8)
c.rect(MARGIN, y - 36, W - 2*MARGIN, 36, fill=1, stroke=1)
c.setFillColor(BG_TITLE)
c.setFont("Helvetica-Bold", 8)
c.drawString(MARGIN + 5, y - 11, "HOW TO USE THIS GUIDE:")
c.setFillColor(BLACK)
c.setFont("Helvetica", 7.5)
intro = [
"1. Read the THEORY section โ understand WHAT a concept is and WHY it matters.",
"2. Read HOW TO SOLVE โ these are the exact steps to follow on the test.",
"3. Follow the WORKED EXAMPLE โ trace through it yourself to check you understand.",
"The cheat sheet you bring to the test has the theory + steps but NOT the examples.",
]
for i, ln in enumerate(intro):
c.drawString(MARGIN + 5, y - 22 - i * 9, ln)
y -= 44
# โโ Two-column layout from here โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# We'll place topics alternating left/right, flowing down the page.
# Each topic starts fresh in left col if remaining space < threshold.
LX = MARGIN # left column x
RX = MARGIN + COL_W + COL_GAP # right column x
def check_space(y_val, needed, pm_obj):
"""If not enough space, start new page and return top y."""
if y_val < 18*mm + needed:
pm_obj.new_page()
return H - 15*mm
return y_val
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 1: ATOMIC STRUCTURE & THE PERIODIC TABLE
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 40, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 1,
"ATOMIC STRUCTURE & THE PERIODIC TABLE", "Questions 44โ50")
# --- split into left and right below topic header ---
ly = y - 2*mm
ry = y - 2*mm
# LEFT: Vocabulary
ly = section_label(pm, LX, ly, COL_W, "โถ KEY VOCABULARY", BG_THEORY, CLR_THEORY)
vocab_items = [
("Ground state", "The lowest energy state of an atom โ electrons are in the closest possible shells."),
("Excited state", "When an electron ABSORBS energy and jumps to a HIGHER shell."),
("Isotopes", "Same element (same protons), different number of NEUTRONS โ different mass. Example: C-12 vs C-14."),
("Allotropes", "Same element, different physical structure. Diamond vs graphite โ both are pure carbon (C)."),
("Alloy", "A MIXTURE with metallic properties. Steel = Fe + C. Bronze = Cu + Sn."),
("Octet rule", "Atoms are most stable when they have 8 electrons in their outer shell."),
]
for term, defn in vocab_items:
c.setFillColor(BG_THEORY)
c.rect(LX, ly - 20, COL_W, 20, fill=1, stroke=0)
c.setFillColor(CLR_THEORY)
c.setFont("Helvetica-Bold", 7)
c.drawString(LX + 4, ly - 9, term)
c.setFillColor(BLACK)
c.setFont("Helvetica", 6.5)
# wrap definition
words = defn.split()
line1 = ""
line2 = ""
for w in words:
if len(line1) + len(w) + 1 < 52:
line1 += (" " if line1 else "") + w
else:
line2 += (" " if line2 else "") + w
c.drawString(LX + 4, ly - 16, line1)
if line2:
# slightly smaller for overflow
c.setFont("Helvetica", 6)
c.drawString(LX + 4, ly - 22.5, line2)
ly -= 26
else:
ly -= 22
ly -= 1
ly -= 3
# LEFT: Electron configuration
ly = section_label(pm, LX, ly, COL_W, "โถ ELECTRON CONFIGURATION โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Electrons fill orbitals from LOWEST to HIGHEST energy.",
"Each orbital type holds a set number of electrons:",
" s = 2 electrons | p = 6 | d = 10 | f = 14",
"Fill order (Aufbau principle):",
" 1s โ 2s โ 2p โ 3s โ 3p โ 4s โ 3d โ 4p โ 5s โ 4d โ 5p",
" โ 4s fills BEFORE 3d โ this is a common exam trap!",
"Shortcut: [noble gas] = use the previous noble gas config",
" then continue filling from where it stopped.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
# RIGHT: Light & photon energy
ry = section_label(pm, RX, ry, COL_W, "โถ LIGHT & ELECTROMAGNETIC SPECTRUM โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Light travels as both a wave AND packets of energy (photons).",
"Three related quantities โ wavelength (ฮป), frequency (ฮฝ), energy (E):",
"",
" c = ฮป ร ฮฝ โ ฮฝ = c / ฮป",
" E = h ร ฮฝ โ E = hc / ฮป",
"",
" c = 3.00 ร 10โธ m/s (speed of light)",
" h = 6.626 ร 10โปยณโด Jยทs (Planck's constant)",
" ฮป in METERS | ฮฝ in Hz (sโปยน) | E in Joules",
"",
"Key relationship: HIGHER frequency = SHORTER wavelength = MORE energy",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: PHOTON ENERGY PROBLEMS", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Identify what you're given: ฮป (wavelength) or ฮฝ (frequency)?",
"If given ฮป, convert to meters first (nm ร 10โปโน = m)",
"Find frequency: ฮฝ = c / ฮป",
"Find energy: E = h ร ฮฝ",
"Check units: answer should be in Joules (J)",
])
ry = example_block(pm, RX, ry, COL_W, [
"ฮป = 500 nm. Find frequency and energy.",
"Convert: 500 nm = 500 ร 10โปโน = 5.00 ร 10โปโท m",
"ฮฝ = c/ฮป = (3.00ร10โธ) / (5.00ร10โปโท) = 6.00 ร 10ยนโด Hz",
"E = hฮฝ = (6.626ร10โปยณโด)(6.00ร10ยนโด) = 3.98 ร 10โปยนโน J",
])
# HOW TO SOLVE config โ goes in left col
ly = section_label(pm, LX, ly, COL_W, "โถ HOW TO SOLVE: ELECTRON CONFIGURATION", BG_HOWTO, CLR_HOWTO)
ly = steps_block(pm, LX, ly, COL_W, [
"Look up (or count) the atomic number Z",
"Find the PREVIOUS noble gas in the periodic table",
"Write [that noble gas] as the shortcut",
"Continue filling: 4s โ 3d โ 4p (remember 4s before 3d!)",
"Count electrons added = Z minus noble gas Z",
])
ly = example_block(pm, LX, ly, COL_W, [
"Germanium (Ge): Z = 32, Period 4, Group 14",
"Previous noble gas: Ar (Z=18) โ write [Ar]",
"Need 32 โ 18 = 14 more electrons",
"Fill: 4sยฒ(2) โ 3dยนโฐ(12) โ 4pยฒ(14) โ",
"Answer: [Ar] 4sยฒ 3dยนโฐ 4pยฒ",
])
ly = warn_box(pm, LX, ly, COL_W, [
"4s fills BEFORE 3d โ always!",
"Transition metals start at group 3 (filling 3d subshell)",
])
# sync columns
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 2: CHEMICAL BONDING
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 60, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 2,
"CHEMICAL BONDING", "Questions 32โ40",
color=colors.HexColor("#4a148c"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ TYPES OF BONDS โ THEORY", BG_THEORY, CLR_THEORY)
ly = table_block(pm, LX, ly, COL_W,
["Type", "How it works", "Who", "Property"],
[
["Ionic", "Metal GIVES eโป to nonmetal", "Metal + Nonmetal", "High MP, forms crystals"],
["Covalent", "Both atoms SHARE electrons", "Nonmetal+Nonmetal", "Lower MP, no ions"],
["Coordinate", "ONE atom donates BOTH electrons", "Special covalent", "e.g. NHโโบ, HโOโบ"],
],
col_ratios=[0.18, 0.36, 0.28, 0.18]
)
ly = section_label(pm, LX, ly, COL_W, "โถ SIGMA & PI BONDS โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Every bond contains one sigma (ฯ) bond (electron density BETWEEN atoms).",
"Extra bonds in double/triple bonds are pi (ฯ) bonds (above/below axis).",
" Single bond = 1ฯ, 0ฯ",
" Double bond = 1ฯ, 1ฯ",
" Triple bond = 1ฯ, 2ฯ โ strongest and shortest",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ BOND LENGTH & STRENGTH โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"SHORTER bond = STRONGER bond = HIGHER bond dissociation energy",
" Triple > Double > Single (strength and energy to break)",
" Single > Double > Triple (length)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
# Right col: polarity + diatomic
ry = section_label(pm, RX, ry, COL_W, "โถ POLARITY & MOLECULAR GEOMETRY โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"A bond is polar when two atoms have DIFFERENT electronegativities",
"(one atom pulls electrons more strongly โ creates ฮด+ and ฮดโ ends).",
"",
"NONPOLAR molecule: bond dipoles CANCEL each other out.",
" โ Must be perfectly SYMMETRIC geometry.",
" โ Example: SiHโ (tetrahedral, 4 equal bonds) = NONPOLAR",
"",
"POLAR molecule: bond dipoles do NOT cancel.",
" โ Usually happens when central atom has LONE PAIRS.",
" โ Lone pairs push the geometry, making it asymmetric.",
" โ Examples: AsHโ, PHโ, HโS โ all polar",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ DIATOMIC ELEMENTS โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"7 elements exist as DIATOMIC pairs in nature โ they never go solo.",
"Memory trick: HOFBrINCl",
" Hโ Oโ Fโ Brโ Iโ Nโ Clโ",
"Always write these with subscript 2 in chemical equations!",
"",
"Noble gases (He, Ne, Ar, Kr, Xe) are MONOATOMIC โ they never bond.",
"Do NOT write Heโ or Arโ.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: COUNT ฯ AND ฯ BONDS", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Draw or identify all bonds in the molecule",
"Every single bond โ count 1ฯ",
"Every double bond โ count 1ฯ + 1ฯ",
"Every triple bond โ count 1ฯ + 2ฯ",
"Add all ฯ together, then all ฯ together",
])
ry = example_block(pm, RX, ry, COL_W, [
"Ethene CโHโ: Structure: HโC=CHโ",
" C=C โ 1ฯ + 1ฯ",
" 4 CโH single bonds โ 4ฯ",
" TOTAL: 5ฯ bonds, 1ฯ bond",
])
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 3: CHEMICAL NOMENCLATURE
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 60, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 3,
"CHEMICAL NOMENCLATURE & FORMULAS", "Questions 27, 35, 36, 41โ43",
color=colors.HexColor("#e65100"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ IONIC COMPOUNDS โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Ionic compounds: metal + nonmetal, charges must BALANCE to zero.",
"",
"Naming rules:",
" 1. Write METAL name first (unchanged)",
" 2. If VARIABLE-CHARGE metal (Fe, Cu, Pb, Sn, Hg, Cr, Mn):",
" โ Figure out the charge from the formula",
" โ Add Roman numeral in parentheses: Fe(III)",
" 3. Write ANION name:",
" Simple nonmetal: add -ide (Clโป = chloride)",
" Polyatomic ion: use its own name (SOโยฒโป = sulfate)",
"",
" -ate = MORE oxygens | -ite = FEWER oxygens",
" hypo- prefix = fewest oxygens (ClOโป = hypochlorite)",
" per- prefix = most oxygens (ClOโโป = perchlorate)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ POLYATOMIC IONS โ MUST MEMORIZE", BG_THEORY, CLR_THEORY)
ly = table_block(pm, LX, ly, COL_W,
["Ion", "Name", "Ion", "Name"],
[
["SOโยฒโป", "sulfate", "ClOโป", "hypochlorite"],
["SOโยฒโป", "sulfite", "ClOโโป", "chlorite"],
["NOโโป", "nitrate", "ClOโโป", "chlorate"],
["NOโโป", "nitrite", "ClOโโป", "perchlorate"],
["POโยณโป", "phosphate", "OHโป", "hydroxide"],
["NHโโบ", "ammonium", "COโยฒโป", "carbonate"],
],
col_ratios=[0.18, 0.32, 0.18, 0.32]
)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: NAME AN IONIC COMPOUND", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Identify the cation (metal) and anion",
"Is the metal VARIABLE-CHARGE? (Fe, Cu, Pb, Sn, Hg, Cr, Mn)",
" If YES: total negative charge รท number of metal atoms = metal charge",
" Write the charge as Roman numeral in ()",
"If NO variable charge: just write the metal name",
"Write the anion name (-ide, -ate, -ite, or polyatomic name)",
])
ry = example_block(pm, RX, ry, COL_W, [
"Feโ(SOโ)โ: 3 sulfate ions ร 2โ = 6โ total negative",
" 2 Fe atoms must balance: 6รท2 = 3+ per Fe",
" โ Iron(III) sulfate",
"Caโ(POโ)โ: Ca is Group 2, always 2+ (NOT variable)",
" โ Calcium phosphate (no Roman numeral needed)",
])
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: WRITE AN IONIC FORMULA", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Write cation (positive) first, anion (negative) second",
"CROSSOVER METHOD: swap the charge numbers as subscripts",
"If subscript is 1, leave it out (don't write CaโClโ, just CaClโ)",
"Reduce if possible: Caยฒโบ + Oยฒโป โ CaO (not CaโOโ)",
"Polyatomic ion with subscript > 1? Wrap in parentheses",
])
ry = example_block(pm, RX, ry, COL_W, [
"Caยฒโบ + POโยณโป: cross charges โ Caโ(POโ)โ",
" Check: 3ร(2+) = 6+ and 2ร(3โ) = 6โ โ",
"Alยณโบ + Oยฒโป: cross โ AlโOโ",
" Check: 2ร(3+) = 6+ and 3ร(2โ) = 6โ โ",
])
ry = section_label(pm, RX, ry, COL_W, "โถ MOLECULAR COMPOUNDS & ACIDS โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Molecular compounds: use GREEK PREFIXES for atom count.",
" 1=mono 2=di 3=tri 4=tetra 5=penta 6=hexa 7=hepta 8=octa",
" NโHโ = dinitrogen tetrahydride",
"",
"Acids (containing H, dissolved in water):",
" -ate ion โ -ic acid: HโSOโ = sulfuric acid",
" -ite ion โ -ous acid: HโSOโ = sulfurous acid",
"",
"Hydrates: Compound โข xHโO",
" Ba(OH)โ โข 8HโO = barium hydroxide octahydrate",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 4: CHEMICAL REACTIONS
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.new_page()
y = H - 15*mm
y = topic_header(pm, LX, y, W - 2*MARGIN, 4,
"CHEMICAL REACTIONS & EQUATIONS", "Questions 28โ31",
color=colors.HexColor("#b71c1c"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ BALANCING EQUATIONS โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Law of Conservation of Mass: atoms cannot be created or destroyed.",
"A balanced equation has the SAME number of each atom on both sides.",
"",
"RULES:",
" โข Only change COEFFICIENTS (numbers in front of formulas)",
" โข NEVER change subscripts inside a formula",
" โข Coefficients must be the smallest whole-number ratio",
" โข Fractions are allowed during balancing but clear them at the end",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ HOW TO SOLVE: BALANCE AN EQUATION", BG_HOWTO, CLR_HOWTO)
ly = steps_block(pm, LX, ly, COL_W, [
"Count atoms of EACH element on both sides",
"Start with elements that appear in FEWEST compounds",
"Add coefficient to balance one element at a time",
"Leave H and O until last (they appear in almost everything)",
"Check ALL elements at the end",
"Clear any fractions by multiplying everything through",
])
ly = example_block(pm, LX, ly, COL_W, [
"SiOโ + HF โ SiFโ + HโO",
"Si: 1=1 โ | F: need 4 on right โ 4HF on left",
"H: 4 on left โ 2HโO on right | O: 2=2 โ",
"Balanced: SiOโ + 4HF โ SiFโ + 2HโO",
"(coefficient for HF = 4)",
])
ly = section_label(pm, LX, ly, COL_W, "โถ REACTION TYPES โ THEORY", BG_THEORY, CLR_THEORY)
ly = table_block(pm, LX, ly, COL_W,
["Type", "Pattern", "Example"],
[
["Synthesis", "A + B โ AB", "2Hโ + Oโ โ 2HโO"],
["Decomposition", "AB โ A + B", "CaCOโ โ CaO + COโ"],
["Single Replace","A + BC โ AC + B", "Zn + HCl โ ZnClโ + Hโ"],
["Double Replace","AB+CD โ AD+CB", "AgNOโ+NaCl โ AgCl+NaNOโ"],
["Combustion", "HC + Oโ โ COโ + HโO", "CHโ+2OโโCOโ+2HโO"],
["Neutralization","Acid+BaseโSalt+Water", "HCl+NaOHโNaCl+HโO"],
],
col_ratios=[0.25, 0.35, 0.40]
)
ry = section_label(pm, RX, ry, COL_W, "โถ PRECIPITATES & NET IONIC โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Precipitate: a solid (s) product that forms when 2 aqueous",
"solutions are mixed. Marked with (s) in the equation.",
"Example: AgNOโ(aq) + NaCl(aq) โ AgCl(s) + NaNOโ(aq)",
"",
"Full ionic equation: split all (aq) compounds into their ions.",
" AgNOโ splits: Agโบ + NOโโป",
" NaCl splits: Naโบ + Clโป",
"",
"Spectator ions: ions that appear UNCHANGED on both sides.",
" โ They don't participate in the reaction. Cross them out.",
"",
"Net ionic equation: what's left after removing spectators.",
" โ Shows only the ACTUAL reaction that occurs.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: NET IONIC EQUATION", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Write and balance the full molecular equation",
"Separate all (aq) ionic compounds into their individual ions",
"Leave (s), (l), (g) species as molecules โ don't split them",
"Identify spectator ions: same ion on both sides unchanged",
"Cross out spectators from both sides",
"What remains = the net ionic equation",
])
ry = example_block(pm, RX, ry, COL_W, [
"HCl(aq) + KOH(aq) โ KCl(aq) + HโO(l)",
"Full ionic: Hโบ + Clโป + Kโบ + OHโป โ Kโบ + Clโป + HโO",
"Spectators: Kโบ and Clโป (same on both sides โ cancel)",
"Net ionic: Hโบ(aq) + OHโป(aq) โ HโO(l)",
])
ry = section_label(pm, RX, ry, COL_W, "โถ NEUTRALIZATION โ THEORY & HOW TO", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Neutralization: Acid + Base โ Salt + Water",
"The acid provides Hโบ, the base provides OHโป.",
"They combine to form water: Hโบ + OHโป โ HโO",
"The remaining ions form the salt.",
"",
"Example: Ba(OH)โ + 2HCl โ BaClโ + 2HโO",
" Ba(OH)โ provides 2 OHโป | 2 HCl provides 2 Hโบ",
" Products: BaClโ (salt) + 2HโO (water)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 5: THE MOLE & MOLAR MASS
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 60, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 5,
"THE MOLE & MOLAR MASS", "Questions 19โ26",
color=colors.HexColor("#1b5e20"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ WHAT IS A MOLE? โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"A mole is just a COUNTING NUMBER, like 'dozen' = 12.",
" 1 mole = 6.02 ร 10ยฒยณ particles (Avogadro's number)",
"",
"Why so big? Because atoms are incredibly tiny.",
"One mole of carbon atoms = 12.01 grams of carbon.",
"",
"MOLAR MASS = the mass (in grams) of exactly 1 mole of a substance.",
" โข For an element: molar mass = atomic mass from periodic table (g/mol)",
" โข For a compound: ADD UP the molar masses of all atoms in formula",
" โข The molar mass IS the conversion factor between grams and moles.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ HOW TO SOLVE: MOLE CALCULATIONS", BG_HOWTO, CLR_HOWTO)
ly = steps_block(pm, LX, ly, COL_W, [
"FIRST: Find the molar mass of the substance",
" (add all atomic masses ร their subscripts in the formula)",
"grams โ moles: moles = grams รท molar mass",
"moles โ grams: grams = moles ร molar mass",
"moles โ particles: particles = moles ร 6.02 ร 10ยฒยณ",
"particles โ moles: moles = particles รท 6.02 ร 10ยฒยณ",
])
ly = example_block(pm, LX, ly, COL_W, [
"How many moles in 100 g of Clโ?",
" MM of Clโ = 2 ร 35.5 = 71.0 g/mol",
" moles = 100 g รท 71.0 g/mol = 1.41 mol",
"Mass of 0.82 mol FeโOโ?",
" MM = 2(55.85) + 3(16.00) = 159.7 g/mol",
" grams = 0.82 ร 159.7 = 130.9 g โ 131 g",
"MM of HโCrOโ: 2(1) + 52 + 4(16) = 118 g/mol",
])
ry = section_label(pm, RX, ry, COL_W, "โถ PERCENT COMPOSITION โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Percent composition tells you what FRACTION of a compound's",
"mass comes from each element.",
"",
" % element = (mass of element in formula / molar mass) ร 100",
"",
"The 'mass of element in formula' = atomic mass ร subscript",
"All percentages in a compound must ADD UP TO 100%.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: PERCENT COMPOSITION", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Calculate molar mass of the entire compound",
"For each element: find its total mass in 1 formula unit",
" (atomic mass ร subscript)",
"Divide element mass by molar mass",
"Multiply by 100 to get percent",
"Verify: all percentages sum to ~100%",
])
ry = example_block(pm, RX, ry, COL_W, [
"% composition of COโ (MM = 12 + 32 = 44 g/mol):",
" % C = (12 / 44) ร 100 = 27.3%",
" % O = (32 / 44) ร 100 = 72.7%",
" Check: 27.3 + 72.7 = 100.0% โ",
])
ry = section_label(pm, RX, ry, COL_W, "โถ EMPIRICAL FORMULA โ THEORY & HOW TO", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"Empirical formula = the SIMPLEST whole-number ratio of atoms.",
"You can find it from percent composition data.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = steps_block(pm, RX, ry, COL_W, [
"Assume 100 g sample โ percent numbers become grams directly",
"Divide each element's grams by its atomic mass โ gives moles",
"Divide ALL mole values by the SMALLEST mole value",
"Round to nearest whole number โ those are your subscripts",
"If you get .5 โ multiply all by 2",
"If you get .33 or .67 โ multiply all by 3",
])
ry = example_block(pm, RX, ry, COL_W, [
"85.6% C, 14.4% H โ assume 100 g",
" C: 85.6 g รท 12 g/mol = 7.13 mol",
" H: 14.4 g รท 1 g/mol = 14.4 mol",
" Divide by smallest (7.13): C=1.00, H=2.02โ2",
" Empirical formula: CHโ",
])
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 6: STOICHIOMETRY
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.new_page()
y = H - 15*mm
y = topic_header(pm, LX, y, W - 2*MARGIN, 6,
"STOICHIOMETRY", "Questions 11โ18",
color=colors.HexColor("#880e4f"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ STOICHIOMETRY โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Stoichiometry uses the balanced equation to predict HOW MUCH",
"of a substance is produced or consumed in a reaction.",
"",
"Basis: Law of Conservation of Mass โ matter is not created or",
"destroyed, just rearranged.",
"",
"Key idea: the COEFFICIENTS in a balanced equation give the",
"MOLAR RATIOS โ how many moles of each substance react/form.",
"",
"Example: CโHโ + 5Oโ โ 3COโ + 4HโO",
" 1 mol propane reacts with 5 mol Oโ to produce 3 mol COโ.",
" Oโ : COโ ratio = 5 : 3 (comes from coefficients only!)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ HOW TO SOLVE: STOICHIOMETRY", BG_HOWTO, CLR_HOWTO)
ly = steps_block(pm, LX, ly, COL_W, [
"Write the BALANCED chemical equation (never skip this!)",
"Convert GIVEN quantity to MOLES:",
" grams รท molar mass = moles",
"Use MOLAR RATIO from balanced equation:",
" moles given ร (coeff wanted / coeff given) = moles wanted",
"Convert moles to DESIRED UNIT:",
" moles ร molar mass = grams",
" moles ร 6.02ร10ยฒยณ = number of particles",
])
ly = example_block(pm, LX, ly, COL_W, [
"CโHโ + 5Oโ โ 3COโ + 4HโO",
"How many g of COโ from 44.0 g CโHโ?",
" MM CโHโ = 3(12)+8(1) = 44.0 g/mol",
" 44.0 g รท 44.0 = 1.00 mol CโHโ",
" 1.00 mol CโHโ ร (3 mol COโ / 1 mol CโHโ) = 3.00 mol COโ",
" 3.00 mol ร 44.0 g/mol = 132 g COโ",
])
ry = section_label(pm, RX, ry, COL_W, "โถ LIMITING REACTANT โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"In real reactions, you rarely have the EXACT right amounts.",
"One reactant runs out first โ it LIMITS how much product forms.",
"",
"Limiting reactant: the one that is COMPLETELY consumed first.",
" โ Determines the maximum amount of product (theoretical yield).",
"",
"Excess reactant: what's LEFT OVER after the reaction stops.",
" โ Some of this reactant remains unreacted.",
"",
"How to identify: see which reactant produces LESS product.",
" The one that makes less = the limiting reactant.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO SOLVE: LIMITING REACTANT", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Balance the equation",
"Convert BOTH given quantities to moles",
"For EACH reactant separately: use molar ratio to find",
" how much product it COULD make (if the other was excess)",
"The reactant that produces LESS product = LIMITING reactant",
"Use the LIMITING reactant's moles to calculate final product",
])
ry = example_block(pm, RX, ry, COL_W, [
"4Fe + 3Oโ โ 2FeโOโ with 5 mol Fe and 4 mol Oโ",
" Fe: 5 mol ร (2 mol FeโOโ / 4 mol Fe) = 2.50 mol product",
" Oโ: 4 mol ร (2 mol FeโOโ / 3 mol Oโ) = 2.67 mol product",
" Fe makes LESS โ Fe is the LIMITING REACTANT",
" Maximum FeโOโ = 2.50 mol",
])
ry = section_label(pm, RX, ry, COL_W, "โถ PERCENT YIELD โ THEORY & HOW TO", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"In real lab experiments, you almost NEVER get the theoretical maximum.",
"Reasons: side reactions, lost material, incomplete reactions.",
"",
"Theoretical yield = max product predicted by stoichiometry (perfect world)",
"Actual yield = product you actually collected in the lab",
"",
" % yield = (actual yield / theoretical yield) ร 100",
"",
"% yield is ALWAYS โค 100% (if >100% something went wrong!)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = example_block(pm, RX, ry, COL_W, [
"Theoretical = 10.0 g, Actual = 8.2 g",
"% yield = (8.2 / 10.0) ร 100 = 82%",
"",
"If % yield = 80%, actual = 15 g, find theoretical:",
" 80 = (15 / theoretical) ร 100",
" theoretical = 15 / 0.80 = 18.75 g",
])
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 7: THERMOCHEMISTRY
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 50, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 7,
"THERMOCHEMISTRY & THERMODYNAMICS", "Questions 7โ9",
color=colors.HexColor("#006064"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ SPECIFIC HEAT โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"When you heat something, energy (q) flows into it.",
"How much energy depends on:",
" โข mass (m) โ more mass = more energy needed",
" โข specific heat (c) โ a property of the material",
" (how much energy to raise 1 gram by 1ยฐC)",
" โข temperature change (ฮT = T_final โ T_initial)",
"",
" q = m ร c ร ฮT",
"",
" q > 0 = heat absorbed (endothermic, temperature rises)",
" q < 0 = heat released (exothermic, temperature drops)",
"",
"Common specific heat values:",
" Water: c = 4.18 J/gยทยฐC | Aluminum: c = 0.900 J/gยทยฐC",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ HOW TO SOLVE: HEAT PROBLEMS", BG_HOWTO, CLR_HOWTO)
ly = steps_block(pm, LX, ly, COL_W, [
"Identify m (grams), c (given or use common values), T_i, T_f",
"Calculate ฮT = T_final โ T_initial (can be negative!)",
"Plug into: q = m ร c ร ฮT",
"Units: grams ร J/gยทยฐC ร ยฐC = J โ",
])
ly = example_block(pm, LX, ly, COL_W, [
"30.0 g Al heated from 20.0ยฐC to 40.0ยฐC",
" c(Al) = 0.900 J/gยทยฐC",
" ฮT = 40.0 โ 20.0 = 20.0ยฐC",
" q = 30.0 ร 0.900 ร 20.0 = 540 J",
])
ry = section_label(pm, RX, ry, COL_W, "โถ CALORIE CONVERSION โ THEORY & HOW TO", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"On food labels: 1 Calorie (capital C) = 1 kilocalorie = 1 kcal",
"In chemistry: 1 calorie (lowercase c) = 4.184 J",
"",
" 1 Cal (food) = 1 kcal = 4184 J",
"",
"To convert Calories to Joules: multiply by 4184",
"To convert Joules to Calories: divide by 4184",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = example_block(pm, RX, ry, COL_W, [
"170 Calories โ Joules:",
" 170 ร 4184 = 711,280 J = 7.11 ร 10โต J",
])
ry = section_label(pm, RX, ry, COL_W, "โถ SPONTANEITY (GIBBS FREE ENERGY) โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"A spontaneous reaction happens ON ITS OWN without constant energy input.",
"",
"Two factors determine spontaneity:",
" ฮH (enthalpy): energy change | ฮS (entropy): disorder change",
" ฮH < 0 = exothermic (releases heat) = FAVORS spontaneity",
" ฮS > 0 = more disorder/randomness = FAVORS spontaneity",
"",
"The Gibbs Free Energy equation (concept only): ฮG = ฮH โ TฮS",
" ฮG < 0 = spontaneous | ฮG > 0 = non-spontaneous",
"",
"MOST IMPORTANT RULE FOR THE EXAM:",
" If ฮH < 0 AND ฮS > 0 โ ALWAYS spontaneous at ANY temperature",
" (ฮG will always be negative no matter what T is)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = table_block(pm, RX, ry, COL_W,
["ฮH", "ฮS", "Spontaneous?"],
[
["< 0 (exo)", "> 0 (more disorder)", "YES, always (any T)"],
["< 0 (exo)", "< 0 (less disorder)", "Only at LOW temperature"],
["> 0 (endo)", "> 0 (more disorder)", "Only at HIGH temperature"],
["> 0 (endo)", "< 0 (less disorder)", "NEVER spontaneous"],
],
col_ratios=[0.22, 0.30, 0.48]
)
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 8: REACTION KINETICS
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.new_page()
y = H - 15*mm
y = topic_header(pm, LX, y, W - 2*MARGIN, 8,
"REACTION KINETICS", "Questions 3โ6",
color=colors.HexColor("#33691e"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ COLLISION THEORY โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"For a chemical reaction to occur, THREE conditions must ALL be met:",
"",
" 1. COLLISION: the particles (atoms, ions, or molecules) must collide.",
" If they never meet, no reaction can happen.",
"",
" 2. ACTIVATION ENERGY: the collision must have ENOUGH energy to",
" break the bonds in the reactants. The minimum energy needed is",
" called the activation energy (Ea).",
"",
" 3. ORIENTATION: particles must collide at the RIGHT angle/position",
" for bonds to form in the product. A head-on crash at the wrong",
" part of the molecule won't work.",
"",
"Reaction rate = how fast reactants turn into products.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ ACTIVATED COMPLEX โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"When reactant particles collide with enough energy, they form a",
"brief, unstable HIGH-ENERGY arrangement called the ACTIVATED COMPLEX",
"(also called the transition state).",
"",
" โข It exists ONLY at the PEAK of the energy diagram",
" โข It is NEITHER reactant nor product",
" โข It immediately either falls apart back to reactants,",
" OR rearranges into products",
" โข It cannot be isolated in the lab",
"",
"On an energy diagram: reactants โ hill (activated complex) โ products",
"The HEIGHT of the hill = activation energy (Ea)",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ FACTORS AFFECTING RATE โ THEORY", BG_THEORY, CLR_THEORY)
ly = table_block(pm, LX, ly, COL_W,
["Factor", "Effect on Rate", "Why"],
[
["โ Temperature", "INCREASES", "Faster particles โ more collisions with enough energy"],
["Add catalyst", "INCREASES", "Lowers Ea (energy hill) โ more collisions succeed"],
["โ Concentration", "INCREASES", "More particles per volume โ more collisions"],
["โ Surface area", "INCREASES", "More exposed particles โ more collisions possible"],
["Remove catalyst", "DECREASES", "Ea goes back up"],
],
col_ratios=[0.25, 0.20, 0.55]
)
ry = section_label(pm, RX, ry, COL_W, "โถ CATALYSTS โ THEORY (IMPORTANT!)", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"A catalyst is a substance that SPEEDS UP a reaction WITHOUT being",
"consumed โ it is present at the start and end unchanged.",
"",
"How it works: provides an ALTERNATIVE REACTION PATHWAY with a",
"LOWER activation energy (lower energy hill to climb).",
"",
"What a catalyst DOES change:",
" โ Lowers activation energy (Ea)",
" โ Increases reaction rate",
"",
"What a catalyst does NOT change:",
" โ ฮH (overall energy difference between reactants and products)",
" โ The equilibrium position",
" โ The identity of products",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO ANSWER KINETICS QUESTIONS", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Rate question: identify what factor changed (temp/conc/catalyst)",
"Temp โ โ rate โ (more collisions AND more energy per collision)",
"Concentration โ โ rate โ (more particles to collide)",
"Catalyst added โ rate โ + Ea โ (but ฮH unchanged!)",
"Catalyst question: always state BOTH effects (rate up, Ea down)",
"Activated complex = at peak of energy diagram, unstable, not product",
])
ry = example_block(pm, RX, ry, COL_W, [
"Q: What happens when a catalyst is added?",
"A: The reaction rate INCREASES because the activation energy",
" (Ea) is LOWERED, so more collisions have enough energy.",
" The overall ฮH (energy of reaction) does NOT change.",
"",
"Q: What is the activated complex?",
"A: The unstable, high-energy intermediate formed when",
" reactant molecules collide โ it exists momentarily at",
" the energy maximum, it is neither reactant nor product.",
])
y = min(ly, ry) - 3*mm
y = divider(pm, MARGIN, y, W - 2*MARGIN)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# TOPIC 9: CHEMICAL EQUILIBRIUM
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
y = check_space(y, 50, pm)
y = topic_header(pm, LX, y, W - 2*MARGIN, 9,
"CHEMICAL EQUILIBRIUM", "Questions 1โ2",
color=colors.HexColor("#37474f"))
ly = y - 2*mm
ry = y - 2*mm
ly = section_label(pm, LX, ly, COL_W, "โถ EQUILIBRIUM โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Many reactions are REVERSIBLE โ products can react to re-form reactants.",
"",
" A + B โ C + D (double arrow = reversible)",
"",
"Equilibrium is reached when:",
" RATE of FORWARD reaction = RATE of REVERSE reaction",
"",
"CRITICAL: At equilibrium, BOTH reactions are still happening!",
" Equilibrium does NOT mean the reactions stopped.",
" It means they happen at the SAME rate โ so concentrations,",
" color, pressure stay CONSTANT (macroscopic properties don't change).",
"",
" The system is DYNAMIC (still changing at the molecular level)",
" but STATIC in appearance.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ly = section_label(pm, LX, ly, COL_W, "โถ EQUILIBRIUM CONSTANT Keq โ THEORY", BG_THEORY, CLR_THEORY)
ly = text_block(pm, LX, ly, COL_W, [
"Keq is a number that describes the RATIO of products to reactants",
"at equilibrium for a given reaction at a specific temperature.",
"",
" Keq > 1 โ more products than reactants at equilibrium",
" Keq < 1 โ more reactants than products at equilibrium",
"",
"MOST IMPORTANT RULES:",
" 1. Keq has ONE valid value at a given TEMPERATURE",
" 2. Changing TEMPERATURE โ Keq VALUE changes",
" 3. Changing concentration or pressure โ equilibrium SHIFTS",
" (Le Chatelier's Principle), but Keq VALUE stays the SAME",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ LE CHATELIER'S PRINCIPLE โ THEORY", BG_THEORY, CLR_THEORY)
ry = text_block(pm, RX, ry, COL_W, [
"If a stress is applied to a system at equilibrium, the system",
"will SHIFT to RELIEVE that stress.",
"",
" A + B โ C + D",
"",
"Types of stresses and how the system responds:",
" Add REACTANT (A or B) โ shifts RIGHT (โ) to make more C and D",
" Add PRODUCT (C or D) โ shifts LEFT (โ) to remove excess",
" Remove REACTANT โ shifts LEFT (โ) to replace it",
" Remove PRODUCT โ shifts RIGHT (โ) to replace it",
" Increase PRESSURE โ shifts toward side with FEWER moles of gas",
" Decrease PRESSURE โ shifts toward side with MORE moles of gas",
" Increase TEMPERATURE (endothermic rxn) โ shifts RIGHT",
" Increase TEMPERATURE (exothermic rxn) โ shifts LEFT",
"",
"โ Concentration/pressure shifts DO NOT change Keq!",
"โ Only temperature changes the actual VALUE of Keq.",
], bg=BG_THEORY, border=CLR_THEORY, line_h=8.5)
ry = section_label(pm, RX, ry, COL_W, "โถ HOW TO ANSWER EQUILIBRIUM QUESTIONS", BG_HOWTO, CLR_HOWTO)
ry = steps_block(pm, RX, ry, COL_W, [
"Identify: is the question about (a) what equilibrium IS,",
" (b) what happens when something is changed (Le Chatelier),",
" or (c) what affects Keq?",
"(a) At equilibrium: fwd rate = rev rate. Both still occurring.",
"(b) Le Chatelier: identify the stress โ state which way it shifts",
"(c) Keq changes: ONLY temperature changes Keq value.",
" Adding concentration/pressure = shift, not Keq change.",
])
ry = example_block(pm, RX, ry, COL_W, [
"Q: What does equilibrium mean?",
"A: Forward and reverse reaction rates are EQUAL.",
" Both reactions still occur โ concentrations stay constant.",
"",
"Q: Add more reactant โ what happens to Keq?",
"A: Keq does NOT change. The equilibrium shifts RIGHT to",
" consume the added reactant, but Keq value stays the same.",
" (Only changing temperature would change Keq.)",
])
y = min(ly, ry) - 3*mm
# Final page โ FORMULA QUICK REFERENCE
pm.new_page()
y = H - 15*mm
c = pm.c
# big header
c.setFillColor(BG_TITLE)
c.rect(0, y - 16, W, 16, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 11)
c.drawCentredString(W/2, y - 12, "MASTER FORMULA & REFERENCE SHEET โ Everything in One Place")
y -= 20
# two column
ly = y
ry = y
# Left: all formulas
ly = section_label(pm, LX, ly, COL_W, "โถ ALL FORMULAS YOU NEED", BG_THEORY, CLR_THEORY)
formulas = [
("Photon frequency", "ฮฝ = c / ฮป", "c=3.00ร10โธ m/s, ฮป in meters"),
("Photon energy", "E = h ร ฮฝ = hc/ฮป", "h=6.626ร10โปยณโด Jยทs"),
("Specific heat", "q = m ร c ร ฮT", "ฮT = T_final โ T_initial"),
("Calorie conversion", "1 Cal = 4184 J", "food Calorie = 1 kcal"),
("Moles from grams", "n = mass / MM", "MM = molar mass (g/mol)"),
("Grams from moles", "g = moles ร MM", ""),
("Avogadro", "1 mol = 6.02ร10ยฒยณ", "particles per mole"),
("% composition", "% = (elem/MM) ร 100", "add all % to check = 100"),
("% yield", "% = actual/theoryร100","always โค 100%"),
("Molar ratio", "coeff_want/coeff_have","from balanced equation"),
]
row_h = 12
c.setFillColor(BG_THEORY)
total_h = len(formulas) * row_h + 4
c.rect(LX, ly - total_h, COL_W, total_h, fill=1, stroke=0)
c.setStrokeColor(CLR_THEORY)
c.setLineWidth(0.4)
c.rect(LX, ly - total_h, COL_W, total_h, fill=0, stroke=1)
for i, (name, formula, note) in enumerate(formulas):
row_y = ly - 2 - i * row_h
if i % 2 == 0:
c.setFillColor(colors.HexColor("#ddeeff"))
c.rect(LX + 0.5, row_y - row_h + 0.5, COL_W - 1, row_h - 0.5, fill=1, stroke=0)
c.setFillColor(CLR_THEORY)
c.setFont("Helvetica-Bold", 6.3)
c.drawString(LX + 3, row_y - 8, name)
c.setFillColor(colors.HexColor("#b71c1c"))
c.setFont("Courier-Bold", 7)
c.drawString(LX + 68, row_y - 8, formula)
c.setFillColor(GREY)
c.setFont("Helvetica", 5.8)
c.drawString(LX + 155, row_y - 8, note)
ly -= total_h + 2*mm
# step-by-step roadmaps summary
ly = section_label(pm, LX, ly, COL_W, "โถ PROBLEM-SOLVING ROADMAPS", BG_HOWTO, CLR_HOWTO)
roadmaps = [
"PHOTON: ฮป(nm)โm โ ฮฝ=c/ฮป โ E=hฮฝ",
"ELECTRON CONFIG: [noble gas] โ fill 4sยฒ3dยนโฐ4pยฒ order",
"NAME IONIC: metal + (Roman# if variable) + anion name",
"WRITE FORMULA: crossover charges as subscripts, reduce",
"MOLE CALC: find MM first โ รทMM for moles โ รMM for grams",
"% COMP: (elem mass / MM) ร 100 for each element",
"EMPIRICAL: %โg รท at.mass โ รท smallest โ whole # ratio",
"STOICH: balance โ to mol โ molar ratio โ to units",
"LIMITING R: bothโmol โ both make product โ smaller = LR",
"% YIELD: actual รท theoretical ร 100",
"HEAT: q = m ร c ร ฮT (ฮT = Tf โ Ti)",
]
ly = text_block(pm, LX, ly, COL_W, roadmaps, bg=BG_HOWTO, border=CLR_HOWTO,
size=6.5, line_h=8.5, color=BLACK)
# RIGHT col: polyatomic ions table + memory tricks + bonding table + spontaneity
ry = section_label(pm, RX, ry, COL_W, "โถ POLYATOMIC IONS โ COMPLETE LIST", BG_THEORY, CLR_THEORY)
ry = table_block(pm, RX, ry, COL_W,
["Ion", "Name", "Ion", "Name"],
[
["SOโยฒโป","sulfate", "ClOโป", "hypochlorite"],
["SOโยฒโป","sulfite", "ClOโโป", "chlorite"],
["NOโโป", "nitrate", "ClOโโป", "chlorate"],
["NOโโป", "nitrite", "ClOโโป", "perchlorate"],
["POโยณโป","phosphate", "OHโป", "hydroxide"],
["NHโโบ", "ammonium", "COโยฒโป", "carbonate"],
["CrOโยฒโป","chromate", "MnOโโป", "permanganate"],
],
col_ratios=[0.20, 0.30, 0.20, 0.30]
)
ry = section_label(pm, RX, ry, COL_W, "โถ BOND & CHARGE QUICK REFERENCE", BG_THEORY, CLR_THEORY)
ry = table_block(pm, RX, ry, COL_W,
["Bond", "ฯ bonds", "ฯ bonds", "Strength", "Length"],
[
["Single", "1", "0", "weakest", "longest"],
["Double", "1", "1", "medium", "medium"],
["Triple", "1", "2", "strongest","shortest"],
],
col_ratios=[0.20, 0.18, 0.18, 0.22, 0.22]
)
ry = section_label(pm, RX, ry, COL_W, "โถ COMMON ION CHARGES", BG_THEORY, CLR_THEORY)
ry = table_block(pm, RX, ry, COL_W,
["Group", "Charge", "Examples"],
[
["1 (alkali metals)", "1+", "Li, Na, K, Rb, Cs"],
["2 (alkaline earth)", "2+", "Be, Mg, Ca, Sr, Ba"],
["13 (Al group)", "3+", "Al, Ga"],
["15 (N group)", "3โ", "N, P, As"],
["16 (O group)", "2โ", "O, S, Se, Te"],
["17 (halogens)", "1โ", "F, Cl, Br, I"],
["18 (noble gases)", "0", "He, Ne, Ar, Kr"],
["Transition metals", "var","Fe(2+/3+) Cu(1+/2+)"],
],
col_ratios=[0.38, 0.15, 0.47]
)
ry = section_label(pm, RX, ry, COL_W, "โถ SPONTANEITY SUMMARY", BG_THEORY, CLR_THEORY)
ry = table_block(pm, RX, ry, COL_W,
["ฮH", "ฮS", "Spontaneous?"],
[
["< 0", "> 0", "ALWAYS (any T)"],
["< 0", "< 0", "Low T only"],
["> 0", "> 0", "High T only"],
["> 0", "< 0", "NEVER"],
],
col_ratios=[0.22, 0.22, 0.56]
)
ry = section_label(pm, RX, ry, COL_W, "โถ GREEK PREFIXES FOR MOLECULAR COMPOUNDS", BG_THEORY, CLR_THEORY)
ry = table_block(pm, RX, ry, COL_W,
["#", "Prefix", "#", "Prefix", "#", "Prefix"],
[
["1","mono", "4","tetra","7","hepta"],
["2","di", "5","penta","8","octa"],
["3","tri", "6","hexa", "9","nona"],
],
col_ratios=[0.08, 0.17, 0.08, 0.17, 0.08, 0.17]
)
pm.save()
cd /home/daytona/workspace/chem-cheatsheet && python3 studyguide_complete.py 2>&โฆ
~/chem-cheatsheet/cheatsheet_final.py
"""
Honors Chemistry โ CHEAT SHEET (2 pages, A4)
Page 1: Periodic Table + full legend (metal/nonmetal/charges/polyatomic ions)
Page 2: Theory + How-To steps for ALL 9 topics. NO worked examples.
Designed to pack maximum useful content into one A4 sheet (print double-sided).
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.pdfgen import canvas as pdfcanvas
W, H = A4
OUT = "/home/daytona/workspace/chem-cheatsheet/HonorsChem_CheatSheet_Final.pdf"
# โโ Palette โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
P = {
"hdr": colors.HexColor("#0d1b4b"),
"hdr2": colors.HexColor("#1a3a7c"),
"topic1": colors.HexColor("#0d47a1"), # atomic
"topic2": colors.HexColor("#4a148c"), # bonding
"topic3": colors.HexColor("#b45309"), # nomenclature
"topic4": colors.HexColor("#991b1b"), # reactions
"topic5": colors.HexColor("#065f46"), # mole
"topic6": colors.HexColor("#7c2d12"), # stoich
"topic7": colors.HexColor("#164e63"), # thermo
"topic8": colors.HexColor("#14532d"), # kinetics
"topic9": colors.HexColor("#374151"), # equilibrium
"thy_bg": colors.HexColor("#eff6ff"),
"thy_bd": colors.HexColor("#3b82f6"),
"how_bg": colors.HexColor("#f0fdf4"),
"how_bd": colors.HexColor("#16a34a"),
"warn_bg": colors.HexColor("#fff7ed"),
"warn_bd": colors.HexColor("#ea580c"),
"tbl_hdr": colors.HexColor("#334155"),
"tbl_alt": colors.HexColor("#f1f5f9"),
# periodic table categories
"alkali": colors.HexColor("#fca5a5"),
"alkaline": colors.HexColor("#fcd34d"),
"transition":colors.HexColor("#93c5fd"),
"postmetal": colors.HexColor("#86efac"),
"metalloid": colors.HexColor("#c4b5fd"),
"nonmetal": colors.HexColor("#fef08a"),
"halogen": colors.HexColor("#67e8f9"),
"noble": colors.HexColor("#f9a8d4"),
"lan": colors.HexColor("#d6b4a0"),
"act": colors.HexColor("#b0c4de"),
"white": colors.white,
"black": colors.black,
"grey": colors.HexColor("#374151"),
"lgrey": colors.HexColor("#e5e7eb"),
"border": colors.HexColor("#94a3b8"),
}
c = pdfcanvas.Canvas(OUT, pagesize=A4)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# HELPER FUNCTIONS
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def hdr_bar(y, text, h=15):
c.setFillColor(P["hdr"])
c.rect(0, y - h, W, h, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 8.5)
c.drawCentredString(W/2, y - h + 3.5, text)
return y - h
def section_bar_full(x, y, w, text, color, h=10):
c.setFillColor(color)
c.rect(x, y - h, w, h, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 6.5)
c.drawString(x + 3, y - h + 2.5, text)
return y - h
def mini_table(x, y, w, headers, rows, col_ratios, size=5.8, rh=8):
col_widths = [w * r for r in col_ratios]
# header
c.setFillColor(P["tbl_hdr"])
c.rect(x, y - rh, w, rh, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", size)
cx = x
for h_txt, cw in zip(headers, col_widths):
c.drawString(cx + 2, y - rh + 2, h_txt)
cx += cw
# rows
for ri, row in enumerate(rows):
ry2 = y - rh * (ri + 2)
c.setFillColor(P["tbl_alt"] if ri % 2 == 0 else P["white"])
c.rect(x, ry2, w, rh, fill=1, stroke=0)
c.setFillColor(P["black"])
c.setFont("Helvetica", size)
cx = x
for cell, cw in zip(row, col_widths):
c.drawString(cx + 2, ry2 + 2, str(cell))
cx += cw
c.setStrokeColor(P["border"])
c.setLineWidth(0.3)
c.rect(x, y - rh * (len(rows) + 1), w, rh * (len(rows) + 1), fill=0, stroke=1)
return y - rh * (len(rows) + 1) - 1.5*mm
def theory_box(x, y, w, lines, lh=7.5, pad=2.5):
total_h = len(lines) * lh + 2 * pad
c.setFillColor(P["thy_bg"])
c.setStrokeColor(P["thy_bd"])
c.setLineWidth(0.4)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
c.setFillColor(P["grey"])
c.setFont("Helvetica", 6)
for i, ln in enumerate(lines):
c.drawString(x + 3, y - pad - i * lh - 5, ln)
return y - total_h - 1*mm
def howto_box(x, y, w, steps, lh=7.5, pad=2.5):
total_h = len(steps) * lh + 2 * pad
c.setFillColor(P["how_bg"])
c.setStrokeColor(P["how_bd"])
c.setLineWidth(0.5)
c.rect(x, y - total_h, w, total_h, fill=1, stroke=1)
for i, step in enumerate(steps):
c.setFillColor(P["how_bd"])
c.setFont("Helvetica-Bold", 6)
c.drawString(x + 3, y - pad - i * lh - 5, f"{i+1}.")
c.setFillColor(P["black"])
c.setFont("Helvetica", 6)
c.drawString(x + 12, y - pad - i * lh - 5, step)
return y - total_h - 1*mm
def warn_line(x, y, w, text):
c.setFillColor(P["warn_bg"])
c.setStrokeColor(P["warn_bd"])
c.setLineWidth(0.4)
c.rect(x, y - 9, w, 9, fill=1, stroke=1)
c.setFillColor(P["warn_bd"])
c.setFont("Helvetica-Bold", 5.5)
c.drawString(x + 2, y - 6.5, "โ ")
c.setFillColor(P["black"])
c.setFont("Helvetica", 5.8)
c.drawString(x + 10, y - 6.5, text)
return y - 10
def topic_bar(x, y, w, num, title, qs, color, h=11):
c.setFillColor(color)
c.roundRect(x, y - h, w, h, 2, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 7)
c.drawString(x + 3, y - h + 2.5, f"T{num}: {title}")
c.setFont("Helvetica", 6)
c.drawRightString(x + w - 3, y - h + 2.5, f"Qs {qs}")
return y - h - 1*mm
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PAGE 1 โ PERIODIC TABLE + LEGEND
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
margin = 5*mm
y = H - margin
y = hdr_bar(y, "HONORS CHEMISTRY โ CHEAT SHEET ยท Page 1: Periodic Table Reference ยท Pendleton High School", h=14)
y -= 2*mm
# โโ PERIODIC TABLE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
table_h_area = H * 0.465
n_rows = 9 # 7 periods + gap + 2 lan/act
n_cols = 18
cw = (W - 2*margin) / n_cols
ch = table_h_area / (n_rows + 0.3)
ELEM = {}
raw = [
# (period, group, symbol, Z, cat, charge)
(1,1,"H",1,"nonmetal","1+/โ"),(1,18,"He",2,"noble","0"),
(2,1,"Li",3,"alkali","1+"),(2,2,"Be",4,"alkaline","2+"),
(2,13,"B",5,"metalloid","3+"),(2,14,"C",6,"nonmetal","4โ"),
(2,15,"N",7,"nonmetal","3โ"),(2,16,"O",8,"nonmetal","2โ"),
(2,17,"F",9,"halogen","1โ"),(2,18,"Ne",10,"noble","0"),
(3,1,"Na",11,"alkali","1+"),(3,2,"Mg",12,"alkaline","2+"),
(3,13,"Al",13,"postmetal","3+"),(3,14,"Si",14,"metalloid","4โ"),
(3,15,"P",15,"nonmetal","3โ"),(3,16,"S",16,"nonmetal","2โ"),
(3,17,"Cl",17,"halogen","1โ"),(3,18,"Ar",18,"noble","0"),
(4,1,"K",19,"alkali","1+"),(4,2,"Ca",20,"alkaline","2+"),
(4,3,"Sc",21,"transition","3+"),(4,4,"Ti",22,"transition","4+"),
(4,5,"V",23,"transition","var"),(4,6,"Cr",24,"transition","var"),
(4,7,"Mn",25,"transition","var"),(4,8,"Fe",26,"transition","var"),
(4,9,"Co",27,"transition","var"),(4,10,"Ni",28,"transition","var"),
(4,11,"Cu",29,"transition","var"),(4,12,"Zn",30,"transition","2+"),
(4,13,"Ga",31,"postmetal","3+"),(4,14,"Ge",32,"metalloid","4โ"),
(4,15,"As",33,"metalloid","3โ"),(4,16,"Se",34,"nonmetal","2โ"),
(4,17,"Br",35,"halogen","1โ"),(4,18,"Kr",36,"noble","0"),
(5,1,"Rb",37,"alkali","1+"),(5,2,"Sr",38,"alkaline","2+"),
(5,3,"Y",39,"transition","3+"),(5,4,"Zr",40,"transition","4+"),
(5,5,"Nb",41,"transition","var"),(5,6,"Mo",42,"transition","var"),
(5,7,"Tc",43,"transition","var"),(5,8,"Ru",44,"transition","var"),
(5,9,"Rh",45,"transition","var"),(5,10,"Pd",46,"transition","var"),
(5,11,"Ag",47,"transition","1+"),(5,12,"Cd",48,"transition","2+"),
(5,13,"In",49,"postmetal","3+"),(5,14,"Sn",50,"postmetal","var"),
(5,15,"Sb",51,"metalloid","3โ"),(5,16,"Te",52,"metalloid","2โ"),
(5,17,"I",53,"halogen","1โ"),(5,18,"Xe",54,"noble","0"),
(6,1,"Cs",55,"alkali","1+"),(6,2,"Ba",56,"alkaline","2+"),
(6,3,"La*",57,"lan","3+"),(6,4,"Hf",72,"transition","4+"),
(6,5,"Ta",73,"transition","5+"),(6,6,"W",74,"transition","var"),
(6,7,"Re",75,"transition","var"),(6,8,"Os",76,"transition","var"),
(6,9,"Ir",77,"transition","var"),(6,10,"Pt",78,"transition","var"),
(6,11,"Au",79,"transition","var"),(6,12,"Hg",80,"transition","var"),
(6,13,"Tl",81,"postmetal","var"),(6,14,"Pb",82,"postmetal","var"),
(6,15,"Bi",83,"postmetal","3+"),(6,16,"Po",84,"metalloid","2โ"),
(6,17,"At",85,"halogen","1โ"),(6,18,"Rn",86,"noble","0"),
(7,1,"Fr",87,"alkali","1+"),(7,2,"Ra",88,"alkaline","2+"),
(7,3,"Ac*",89,"act","3+"),
]
cat_color = {
"alkali":P["alkali"],"alkaline":P["alkaline"],"transition":P["transition"],
"postmetal":P["postmetal"],"metalloid":P["metalloid"],"nonmetal":P["nonmetal"],
"halogen":P["halogen"],"noble":P["noble"],"lan":P["lan"],"act":P["act"],
}
def draw_cell(period, group, sym, Z, cat, charge, x_extra=0, y_extra=0):
col = group - 1
row = period - 1
x = margin + col * cw + x_extra
ey = y - (row + 1) * ch + y_extra
bg = cat_color.get(cat, P["lgrey"])
c.setFillColor(bg)
c.setStrokeColor(P["border"])
c.setLineWidth(0.25)
c.rect(x + 0.3, ey + 0.3, cw - 0.6, ch - 0.6, fill=1, stroke=1)
# atomic number
c.setFillColor(colors.HexColor("#475569"))
c.setFont("Helvetica", 3.8)
c.drawString(x + 1.5, ey + ch - 5, str(Z))
# symbol
c.setFillColor(P["black"])
fsz = 7 if len(sym) <= 2 else 5.5
c.setFont("Helvetica-Bold", fsz)
c.drawCentredString(x + cw/2, ey + ch/2 - 2.5, sym)
# charge
c.setFillColor(colors.HexColor("#dc2626"))
c.setFont("Helvetica", 3.5)
c.drawCentredString(x + cw/2, ey + 1.5, charge)
# Group labels
for g in range(1, 19):
gx = margin + (g - 1) * cw + cw/2
c.setFillColor(P["hdr2"])
c.setFont("Helvetica-Bold", 5)
c.drawCentredString(gx, y + 0.5*mm, str(g))
# Period labels
for p in range(1, 8):
py2 = y - p * ch + ch/2 - 2
c.setFillColor(P["hdr2"])
c.setFont("Helvetica-Bold", 5.5)
c.drawRightString(margin - 1, py2, str(p))
# Draw main table
for (period, group, sym, Z, cat, charge) in raw:
draw_cell(period, group, sym, Z, cat, charge)
# Lanthanides / Actinides
lan_data = [
("La",57,"lan","3+"),("Ce",58,"lan","3+"),("Pr",59,"lan","3+"),
("Nd",60,"lan","3+"),("Pm",61,"lan","var"),("Sm",62,"lan","3+"),
("Eu",63,"lan","3+"),("Gd",64,"lan","3+"),("Tb",65,"lan","3+"),
("Dy",66,"lan","3+"),("Ho",67,"lan","3+"),("Er",68,"lan","3+"),
("Tm",69,"lan","3+"),("Yb",70,"lan","2+"),("Lu",71,"lan","3+"),
]
act_data = [
("Ac",89,"act","3+"),("Th",90,"act","4+"),("Pa",91,"act","5+"),
("U",92,"act","var"),("Np",93,"act","var"),("Pu",94,"act","var"),
("Am",95,"act","3+"),("Cm",96,"act","3+"),("Bk",97,"act","3+"),
("Cf",98,"act","3+"),("Es",99,"act","3+"),("Fm",100,"act","3+"),
("Md",101,"act","3+"),("No",102,"act","2+"),("Lr",103,"act","3+"),
]
lan_y_off = -1.35 * ch
act_y_off = -2.1 * ch
for i, (sym, Z, cat, charge) in enumerate(lan_data):
col = i + 3
row = 7
x = margin + col * cw
ey = y - (row + 1) * ch + lan_y_off
bg = cat_color.get(cat, P["lgrey"])
c.setFillColor(bg)
c.setStrokeColor(P["border"])
c.setLineWidth(0.25)
c.rect(x + 0.3, ey + 0.3, cw - 0.6, ch - 0.6, fill=1, stroke=1)
c.setFillColor(P["black"])
c.setFont("Helvetica-Bold", 6.5)
c.drawCentredString(x + cw/2, ey + ch/2 - 2.5, sym)
c.setFillColor(colors.HexColor("#dc2626"))
c.setFont("Helvetica", 3.5)
c.drawCentredString(x + cw/2, ey + 1.5, charge)
for i, (sym, Z, cat, charge) in enumerate(act_data):
col = i + 3
row = 8
x = margin + col * cw
ey = y - (row + 1) * ch + act_y_off
bg = cat_color.get(cat, P["lgrey"])
c.setFillColor(bg)
c.setStrokeColor(P["border"])
c.setLineWidth(0.25)
c.rect(x + 0.3, ey + 0.3, cw - 0.6, ch - 0.6, fill=1, stroke=1)
c.setFillColor(P["black"])
c.setFont("Helvetica-Bold", 6.5)
c.drawCentredString(x + cw/2, ey + ch/2 - 2.5, sym)
c.setFillColor(colors.HexColor("#dc2626"))
c.setFont("Helvetica", 3.5)
c.drawCentredString(x + cw/2, ey + 1.5, charge)
# Figure out where table ends
table_bottom = y - 9 * ch + act_y_off - 3*mm
# โโ LEGEND โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
legend_y = table_bottom - 2*mm
c.setFillColor(P["hdr"])
c.rect(margin, legend_y - 11, W - 2*margin, 11, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(W/2, legend_y - 8, "PERIODIC TABLE KEY โ Colors, Charges, and Special Groups")
legend_y -= 13
# Category swatches (2 rows ร 4)
cats = [
("Alkali Metals Gp1", "alkali", "1+ charge (Li,Na,K)"),
("Alkaline Earth Gp2","alkaline", "2+ charge (Mg,Ca,Ba)"),
("Transition Metals", "transition", "Variable charge (Fe,Cu,Cr)"),
("Post-Trans. Metals","postmetal", "Al(3+),Pb,Sn,Tl var"),
("Metalloids", "metalloid", "Staircase line: B,Si,Ge,As"),
("Nonmetals", "nonmetal", "Neg ions (Oยฒโป,Nยณโป,Sยฒโป)"),
("Halogens Gp17", "halogen", "1โ charge (F,Cl,Br,I)"),
("Noble Gases Gp18", "noble", "0 charge โ never bond"),
]
bw = (W - 2*margin) / 4
bh = 18
for i, (name, cat, desc) in enumerate(cats):
col = i % 4
row = i // 4
bx = margin + col * bw
by = legend_y - row * (bh + 2)
c.setFillColor(cat_color[cat])
c.setStrokeColor(P["border"])
c.setLineWidth(0.4)
c.rect(bx, by - bh, bw - 2, bh, fill=1, stroke=1)
c.setFillColor(P["black"])
c.setFont("Helvetica-Bold", 6)
c.drawString(bx + 2, by - 8, name)
c.setFillColor(P["grey"])
c.setFont("Helvetica", 5.5)
c.drawString(bx + 2, by - 15, desc)
legend_y -= 2 * (bh + 2) + 2*mm
# Metal / nonmetal divider note
c.setFillColor(P["hdr2"])
c.setFont("Helvetica-Bold", 6.5)
c.drawString(margin, legend_y, "METALS (left of staircase line) โโ METALLOIDS (on staircase) โโ NONMETALS (right of staircase)")
legend_y -= 6*mm
# Ion charges table
c.setFillColor(P["hdr"])
c.rect(margin, legend_y - 10, W - 2*margin, 10, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(W/2, legend_y - 7.5, "COMMON ION CHARGES โ What charge does each group form?")
legend_y -= 12
charge_data = [
("Group 1","1+","Li,Na,K,Rb,Cs"),
("Group 2","2+","Be,Mg,Ca,Sr,Ba"),
("Group 13","3+","Al,Ga,In"),
("Group 15","3โ","N,P,As"),
("Group 16","2โ","O,S,Se,Te"),
("Group 17","1โ","F,Cl,Br,I"),
("Group 18","0","He,Ne,Ar,Kr"),
("Transition","VAR","Fe,Cu,Cr,Mn,Pb"),
]
ccw = (W - 2*margin) / 8
cch = 20
for i, (grp, chg, ex) in enumerate(charge_data):
cx2 = margin + i * ccw
bg = P["alkali"] if i == 0 else P["alkaline"] if i == 1 else P["postmetal"] if i == 2 else \
P["nonmetal"] if i < 6 else P["noble"] if i == 6 else P["transition"]
c.setFillColor(bg)
c.setStrokeColor(P["border"])
c.setLineWidth(0.4)
c.rect(cx2, legend_y - cch, ccw - 1, cch, fill=1, stroke=1)
c.setFillColor(P["black"])
c.setFont("Helvetica-Bold", 6)
c.drawCentredString(cx2 + ccw/2, legend_y - 8, grp)
c.setFillColor(P["hdr"])
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(cx2 + ccw/2, legend_y - 16, chg)
legend_y -= cch + 1*mm
# examples row
c.setFillColor(P["grey"])
c.setFont("Helvetica", 5.5)
for i, (grp, chg, ex) in enumerate(charge_data):
cx2 = margin + i * ccw + ccw/2
c.drawCentredString(cx2, legend_y, ex)
legend_y -= 6*mm
# Special elements + polyatomic ions in two columns
half = (W - 2*margin - 3*mm) / 2
lx2 = margin
rx2 = margin + half + 3*mm
# LEFT: special elements
c.setFillColor(colors.HexColor("#dbeafe"))
c.setStrokeColor(P["topic1"])
c.setLineWidth(0.5)
spec_h = 36
c.rect(lx2, legend_y - spec_h, half, spec_h, fill=1, stroke=1)
c.setFillColor(P["hdr"])
c.setFont("Helvetica-Bold", 6.5)
c.drawString(lx2 + 3, legend_y - 9, "โ
DIATOMIC (HOFBrINCl) โ always paired:")
c.setFillColor(P["black"])
c.setFont("Helvetica", 6.5)
c.drawString(lx2 + 3, legend_y - 17, "Hโ Oโ Fโ Brโ Iโ Nโ Clโ")
c.setFillColor(P["hdr"])
c.setFont("Helvetica-Bold", 6.5)
c.drawString(lx2 + 3, legend_y - 26, "โ
NOBLE GASES โ monoatomic, never bond:")
c.setFillColor(P["black"])
c.setFont("Helvetica", 6.5)
c.drawString(lx2 + 3, legend_y - 34, "He Ne Ar Kr Xe Rn (write alone, never as Heโ!)")
# RIGHT: variable charge metals
c.setFillColor(colors.HexColor("#fef3c7"))
c.setStrokeColor(P["warn_bd"])
c.setLineWidth(0.5)
c.rect(rx2, legend_y - spec_h, half, spec_h, fill=1, stroke=1)
c.setFillColor(P["warn_bd"])
c.setFont("Helvetica-Bold", 6.5)
c.drawString(rx2 + 3, legend_y - 9, "โ
VARIABLE-CHARGE METALS (need Roman numerals):")
c.setFillColor(P["black"])
c.setFont("Helvetica", 6.3)
c.drawString(rx2 + 3, legend_y - 17, "Fe: 2+ (iron II) or 3+ (iron III)")
c.drawString(rx2 + 3, legend_y - 24, "Cu: 1+ (copper I) or 2+ (copper II)")
c.drawString(rx2 + 3, legend_y - 31, "Pb: 2+ or 4+ Sn: 2+ or 4+ Hg: 1+ or 2+")
legend_y -= spec_h + 2*mm
# Polyatomic ions โ full width, compact
c.setFillColor(colors.HexColor("#4a148c"))
c.rect(margin, legend_y - 10, W - 2*margin, 10, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(W/2, legend_y - 7.5, "POLYATOMIC IONS (memorize all of these!)")
legend_y -= 12
ions = [
("SOโยฒโป","sulfate"),("SOโยฒโป","sulfite"),("NOโโป","nitrate"),
("NOโโป","nitrite"),("POโยณโป","phosphate"),("OHโป","hydroxide"),
("NHโโบ","ammonium"),("COโยฒโป","carbonate"),("ClOโป","hypochlorite"),
("ClOโโป","chlorite"),("ClOโโป","chlorate"),("ClOโโป","perchlorate"),
]
icw = (W - 2*margin) / 6
irh = 10
for i, (ion, name) in enumerate(ions):
col = i % 6
row = i // 6
ix = margin + col * icw
iy = legend_y - row * irh
ibg = colors.HexColor("#ede7f6") if col % 2 == 0 else colors.HexColor("#f3e5f5")
c.setFillColor(ibg)
c.setStrokeColor(colors.HexColor("#7b1fa2"))
c.setLineWidth(0.3)
c.rect(ix, iy - irh, icw - 0.5, irh, fill=1, stroke=1)
c.setFillColor(colors.HexColor("#4a148c"))
c.setFont("Helvetica-Bold", 6.5)
c.drawString(ix + 2, iy - irh + 2.5, ion)
c.setFillColor(P["grey"])
c.setFont("Helvetica", 6)
c.drawString(ix + 28, iy - irh + 2.5, name)
legend_y -= 2 * irh + 2*mm
# Memory trick strip
c.setFillColor(colors.HexColor("#fff7ed"))
c.setStrokeColor(P["warn_bd"])
c.setLineWidth(0.5)
trick_h = 14
c.rect(margin, legend_y - trick_h, W - 2*margin, trick_h, fill=1, stroke=1)
c.setFillColor(P["warn_bd"])
c.setFont("Helvetica-Bold", 6)
c.drawString(margin + 3, legend_y - 8, "MEMORY TRICKS:")
c.setFillColor(P["black"])
c.setFont("Helvetica", 6)
c.drawString(margin + 75, legend_y - 8,
"-ate = MORE oxygens | -ite = FEWER oxygens | hypo- = fewest O | per- = most O")
c.drawString(margin + 3, legend_y - trick_h + 2,
"Electron config fill order: 1s 2s 2p 3s 3p 4s 3d 4p 5s 4d 5p ... (4s BEFORE 3d!)")
# Footer
c.setFillColor(P["hdr"])
c.rect(0, 0, W, 10, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica", 5.5)
c.drawCentredString(W/2, 3, "Page 1 of 2 ยท Flip for Step-by-Step Problem Solving โ Pendleton High School ยท Honors Chemistry Final Exam")
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# PAGE 2 โ THEORY + HOW-TO (NO EXAMPLES)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
c.showPage()
c.setPageSize(A4)
# light bg
c.setFillColor(colors.HexColor("#f8fafc"))
c.rect(0, 0, W, H, fill=1, stroke=0)
y = H - margin
y = hdr_bar(y, "PAGE 2: THEORY + HOW-TO STEPS FOR ALL 9 TOPICS ยท No examples โ study those separately", h=14)
y -= 2*mm
MARGIN2 = margin
COL = (W - 2*MARGIN2 - 3*mm) / 2
LX = MARGIN2
RX = MARGIN2 + COL + 3*mm
ly = y
ry = y
# โโ TOPIC 1: Atomic Structure โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ly = topic_bar(LX, ly, COL, 1, "ATOMIC STRUCTURE & PERIODIC TABLE", "44โ50", P["topic1"])
ly = theory_box(LX, ly, COL, [
"Ground state = lowest energy; Excited = electron absorbed energy, jumped up",
"Isotopes = same element, diff neutrons โ diff mass (e.g. C-12 vs C-14)",
"Allotropes = same element, diff structure (diamond/graphite = both carbon)",
"Alloy = metallic mixture (steel=Fe+C, bronze=Cu+Sn)",
"Octet rule: atoms are stable with 8 electrons in outer shell",
"Fill order: 1s 2s 2p 3s 3p [4s 3d] 4p 5s 4d 5p ... (4s BEFORE 3d!)",
])
ly = howto_box(LX, ly, COL, [
"Electron config: find Z, find prev. noble gas, write [NG]",
"Continue filling: 4sยฒ โ 3dยนโฐ โ 4pยฒ (32โ18=14 eโป for Ge)",
"Ge (Z=32): [Ar] 4sยฒ 3dยนโฐ 4pยฒ",
"Light: ฮฝ = c/ฮป then E = hฮฝ (ฮป MUST be in meters!)",
"c=3.00ร10โธ m/s h=6.626ร10โปยณโด Jยทs",
])
# โโ TOPIC 2: Chemical Bonding โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ly = topic_bar(LX, ly, COL, 2, "CHEMICAL BONDING", "32โ40", P["topic2"])
ly = theory_box(LX, ly, COL, [
"Ionic: Metal GIVES eโป to nonmetal โ forms crystals, HIGH melting point",
"Covalent: Nonmetal+Nonmetal SHARE eโป",
"Coordinate covalent: ONE atom donates BOTH electrons (e.g. NHโโบ)",
"Single=1ฯ,0ฯ | Double=1ฯ,1ฯ | Triple=1ฯ,2ฯ",
"Shorter bond = Stronger = Higher energy to break",
"Nonpolar: symmetric (SiHโ tetrahedral) | Polar: has lone pairs (HโS,PHโ)",
"HOFBrINCl: 7 diatomic elements Hโ Oโ Fโ Brโ Iโ Nโ Clโ",
])
ly = howto_box(LX, ly, COL, [
"Count ฯ/ฯ: every bond has 1ฯ; double adds 1ฯ; triple adds 2ฯ",
"CโHโ: C=C(1ฯ+1ฯ) + 4 C-H(4ฯ) = 5ฯ total, 1ฯ total",
"Polarity: lone pairs on central atom โ polar molecule",
"Bond type from formula: = is double, โก is triple",
])
# โโ TOPIC 3: Nomenclature โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ly = topic_bar(LX, ly, COL, 3, "NOMENCLATURE & FORMULAS", "27,35,36,41โ43", P["topic3"])
ly = theory_box(LX, ly, COL, [
"Ionic naming: metal name + (Roman# if variable charge) + anion name",
"Variable charge metals: Fe, Cu, Pb, Sn, Hg, Cr, Mn",
"-ate = more O | -ite = fewer O | hypo=fewest | per=most",
"Hydrate: CompoundโขxHโO (e.g. Ba(OH)โโข8HโO = octahydrate)",
"Molecular: Greek prefixes (di-Nโ, tetra-4, hexa-6, octa-8...)",
"Acids: -ate ion โ -ic acid (HโSOโ=sulfuric) | -ite โ -ous (HโSOโ=sulfurous)",
])
ly = howto_box(LX, ly, COL, [
"Name ionic: identify metal, check if variable charge",
"Variable? Count total negative charge รท # metal atoms = charge",
"Write Roman numeral in (): Feโ(SOโ)โ โ 3ร2โ=6โ โ Fe=3+ โ Iron(III) sulfate",
"Write formula: CROSSOVER method โ swap charges as subscripts",
"Caยฒโบ+POโยณโป โ Caโ(POโ)โ | reduce if both even (CaโOโโCaO)",
])
ly = warn_line(LX, ly, COL, "Polyatomic with subscript > 1 MUST have parentheses: (POโ)โ not POโโ")
# โโ TOPIC 4: Reactions โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ly = topic_bar(LX, ly, COL, 4, "CHEMICAL REACTIONS & EQUATIONS", "28โ31", P["topic4"])
ly = theory_box(LX, ly, COL, [
"Conservation of Mass: same atoms on both sides โ only coefficients change",
"Precipitate: solid (s) product from 2 aq. solutions (e.g. AgCl(s))",
"Spectator ions: appear UNCHANGED on both sides โ remove for net ionic",
"Neutralization: Acid + Base โ Salt + Water",
"Net ionic for any neutralization: Hโบ(aq) + OHโป(aq) โ HโO(l)",
])
ly = howto_box(LX, ly, COL, [
"Balance: count each element, add coefficients (NOT subscripts)",
"Balance metals first, then nonmetals, then H, then O last",
"Net ionic: split all (aq), keep (s)(l)(g) whole, cancel spectators",
"SiOโ+4HFโSiFโ+2HโO (coeff of HF=4)",
"Neutralization: Ba(OH)โ+2HClโBaClโ+2HโO",
])
# RIGHT COLUMN starts here
# โโ TOPIC 5: Mole โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = topic_bar(RX, ry, COL, 5, "THE MOLE & MOLAR MASS", "19โ26", P["topic5"])
ry = theory_box(RX, ry, COL, [
"1 mole = 6.02ร10ยฒยณ particles (Avogadro's number)",
"Molar mass = grams per mole of a substance (from periodic table)",
"Compound MM: add atomic masses ร subscripts for each element",
"Stoichiometry based on Law of Conservation of Mass",
"Conversions: gโmol (รทMM) | molโg (รMM) | molโparticles (รAvogadro)",
])
ry = howto_box(RX, ry, COL, [
"Step 1: Calculate molar mass (add all atomic masses in formula)",
"Grams โ Moles: n = mass รท molar mass",
"Moles โ Grams: g = moles ร molar mass",
"Moles โ Particles: N = moles ร 6.02ร10ยฒยณ",
"% comp: % = (elem. mass in formula / MM) ร 100 โ must sum to 100",
"Empirical: %โg โ รทat.mass โ รทsmallest โ whole # ratio",
])
ry = warn_line(RX, ry, COL, "HโCrOโ: MM=2(1)+52+4(16)=118 | Clโ: 71.0 | FeโOโ: 159.7 g/mol")
# โโ TOPIC 6: Stoichiometry โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = topic_bar(RX, ry, COL, 6, "STOICHIOMETRY", "11โ18", P["topic6"])
ry = theory_box(RX, ry, COL, [
"Coefficients in balanced equation = MOLAR RATIOS",
"Limiting reactant: runs out first, determines max product",
"Excess reactant: what's left over after reaction stops",
"Theoretical yield: max product from stoichiometry (perfect conditions)",
"Actual yield: what you really get in the lab (always โค theoretical)",
"% yield = (actual รท theoretical) ร 100",
])
ry = howto_box(RX, ry, COL, [
"ALWAYS STEP 1: write and balance the equation",
"Stoich: given(g) รท MM โ mol โ ร molar ratio โ mol wanted โ ร MM",
"Limiting R: convert BOTH reactants to mol โ each makes product",
" the one making LESS product = LIMITING REACTANT",
"% yield: actual รท theoretical ร 100 (must be โค 100%)",
"Molar ratio CโHโ+5Oโโ3COโ+4HโO: Oโ:COโ = 5:3",
])
# โโ TOPIC 7: Thermochemistry โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = topic_bar(RX, ry, COL, 7, "THERMOCHEMISTRY", "7โ9", P["topic7"])
ry = theory_box(RX, ry, COL, [
"q = m ร c ร ฮT (q=heat J, m=mass g, c=spec.heat J/gยฐC, ฮT=TfโTi)",
"Water: c=4.18 J/gยฐC | Aluminum: c=0.900 J/gยฐC",
"1 Cal (food) = 1 kcal = 4184 J",
"Spontaneous if ฮH<0 AND ฮS>0 โ always spontaneous (any temp)",
"ฮG = ฮH โ TฮS | ฮG<0 = spontaneous | ฮG>0 = non-spontaneous",
])
ry = mini_table(RX, ry, COL,
["ฮH", "ฮS", "Spontaneous?"],
[["<0","<0","Low T only"],["<0",">0","ALWAYS โ"],
[">0","<0","NEVER โ"],[">0",">0","High T only"]],
[0.22,0.22,0.56], size=5.8, rh=7.5
)
ry = howto_box(RX, ry, COL, [
"Heat: find m,c,Ti,Tf โ ฮT=TfโTi โ q=mรcรฮT (answer in J)",
"CalโJ: multiply by 4184 | JโCal: divide by 4184",
"Spontaneity: state both ฮH and ฮS signs, use table above",
])
# โโ TOPIC 8: Kinetics โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = topic_bar(RX, ry, COL, 8, "REACTION KINETICS", "3โ6", P["topic8"])
ry = theory_box(RX, ry, COL, [
"Collision theory: must (1) collide, (2) have โฅ activation energy, (3) right orientation",
"Activated complex: unstable high-E intermediate at energy maximum",
" โ NOT a reactant, NOT a product โ exists only momentarily",
"โTemp โ rate โ (faster particles, more energetic collisions)",
"Catalyst โ rate โ, Ea โ BUT ฮH (overall energy) UNCHANGED",
"โConcentration or โSurface area โ rate โ (more collisions)",
])
ry = howto_box(RX, ry, COL, [
"Rate question: identify which factor changed โ state effect on rate",
"Catalyst question: rate INCREASES + Ea DECREASES + ฮH unchanged",
"Activated complex = at PEAK of energy diagram, unstable, not product",
"Temp up = rate up because MORE collisions have ENOUGH energy",
])
# โโ TOPIC 9: Equilibrium โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ry = topic_bar(RX, ry, COL, 9, "CHEMICAL EQUILIBRIUM", "1โ2", P["topic9"])
ry = theory_box(RX, ry, COL, [
"Equilibrium: forward rate = reverse rate (BOTH still occurring!)",
"NOT stopped โ still dynamic, but concentrations/pressure stay constant",
"Keq valid ONLY at ONE specific temperature",
"Only TEMPERATURE changes the VALUE of Keq",
"Concentration/pressure changes SHIFT equilibrium (not Keq value)",
"Le Chatelier: stress โ system shifts to relieve it",
" Add reactant โ shifts right | Add product โ shifts left",
" โPressure โ shifts to fewer moles of gas",
])
ry = howto_box(RX, ry, COL, [
"What is equilibrium? Fwd=Rev rate, both occurring, conc. constant",
"Something added: identify it โ state which direction eq. shifts",
"Does Keq change? Only if TEMPERATURE changes. Conc/pressure = no",
"Le Chat: add more A+BโC+D reactant โ shifts โ makes more C,D",
])
# โโ BOTTOM STRIP: Formula quick-ref โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
bottom_y = min(ly, ry) - 2*mm
c.setFillColor(P["hdr"])
c.rect(MARGIN2, bottom_y - 11, W - 2*MARGIN2, 11, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(W/2, bottom_y - 8, "ALL FORMULAS IN ONE LINE: ฮฝ=c/ฮป ยท E=hฮฝ ยท q=mcฮT ยท 1Cal=4184J ยท n=mass/MM ยท %comp=(elem/MM)ร100 ยท %yield=(actual/theoretical)ร100 ยท Avogadro=6.02ร10ยฒยณ")
bottom_y -= 13
# Footer
c.setFillColor(P["hdr"])
c.rect(0, 0, W, 10, fill=1, stroke=0)
c.setFillColor(P["white"])
c.setFont("Helvetica", 5.5)
c.drawCentredString(W/2, 3, "Page 2 of 2 ยท Pendleton High School ยท Honors Chemistry Final Exam ยท Print double-sided on one A4 sheet")
c.save()
print(f"โ
Saved: {OUT}")
cd /home/daytona/workspace/chem-cheatsheet && python3 cheatsheet_final.py 2>&1
ls -lh /home/daytona/workspace/chem-cheatsheet/*.pdf
HonorsChem StudyGuide Complete
PDF Document ยท PDF
HonorsChem CheatSheet Final
PDF Document ยท PDF