final lessons

This commit is contained in:
2026-06-07 10:44:05 +02:00
parent ceea2f206a
commit 39ec1bac72
105 changed files with 7789 additions and 1515 deletions

View File

@@ -0,0 +1,102 @@
# Les 8 — Huiswerk
## QuickPoll polish + bonus features
**Deadline:** Voor Les 9
**Inleveren:** GitHub repo via Teams
---
## Opdracht 1 — Deploy naar Vercel
Push je app naar GitHub (als nog niet), dan:
1. vercel.com → Add New Project → import jouw repo
2. Add env vars: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`
3. Deploy
Test op productie URL — moet werken.
Noteer in `DEPLOY.md`: productie URL.
---
## Opdracht 2 — Voeg validatie toe
Server actions valideren nu te min. Voeg toe:
- Min 3, max 100 karakters voor poll-titel
- Min 2, max 10 opties
- Toon validation errors **inline** (geen throw)
- Form blijft ingevuld bij error
Hint: return error-object uit server action, gebruik `useActionState` in form.
---
## Opdracht 3 — Optimistic UI
Voeg `useOptimistic` toe aan VoteForm voor instant vote-feedback:
```tsx
const [optimisticOptions, addOptimisticVote] = useOptimistic(
poll.options,
(state, optionId) => state.map(o =>
o.id === optionId ? { ...o, votes: o.votes + 1 } : o
)
);
```
Bij click: roep `addOptimisticVote(optionId)` aan voor de server call.
---
## Opdracht 4 — TypeScript types
Genereer types vanuit Supabase (uit Les 7 bonus):
```bash
pnpm dlx supabase gen types typescript --linked > types/database.ts
```
Update `lib/supabase.ts`:
```typescript
import type { Database } from "@/types/database";
export const supabase = createClient<Database>(...);
```
Refactor één query om de gegenereerde types te gebruiken (autocomplete moet werken).
---
## Opdracht 5 — Reflectie (250 woorden)
In `REFLECTIE.md`:
- Wat voelt natuurlijk aan Server Actions + Supabase combo?
- Welke RPC functions zou je nog meer willen maken?
- Wat verbaast je over Supabase t.o.v. eerdere database-ervaringen?
- Wat is je grootste vraag voor Les 9 (Auth)?
---
## Bonus
- **Realtime updates** — `supabase.channel(...).on("postgres_changes", ...)` voor live vote-updates
- **Delete polls** — admin-page met delete button
- **Public link sharing** — kopieer-URL knop voor polls
---
## Inleveren
GitHub repo URL + Vercel productie URL via Teams. Werkende app + REFLECTIE.md + DEPLOY.md.
---
## Tips
- **Validation** is meestal het vervelendste — werk er gestaag aan
- **Optimistic UI** voelt magisch maar is lastig — test edge cases
- **Tijd:** ~2-3 uur
Volgende les: Supabase Auth. We laten users inloggen + RLS per user.

View File

@@ -0,0 +1,124 @@
%PDF-1.4
%<25><><EFBFBD><EFBFBD> ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
4 0 obj
<<
/BaseFont /Symbol /Name /F3 /Subtype /Type1 /Type /Font
>>
endobj
5 0 obj
<<
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
>>
endobj
6 0 obj
<<
/Contents 12 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
7 0 obj
<<
/Contents 13 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
8 0 obj
<<
/Contents 14 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 11 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
9 0 obj
<<
/PageMode /UseNone /Pages 11 0 R /Type /Catalog
>>
endobj
10 0 obj
<<
/Author (NOVI Hogeschool Utrecht) /CreationDate (D:20260607080655+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260607080655+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title (Huiswerk) /Trapped /False
>>
endobj
11 0 obj
<<
/Count 3 /Kids [ 6 0 R 7 0 R 8 0 R ] /Type /Pages
>>
endobj
12 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1785
>>
stream
GauHLD,]1K&H;*)YohF9<@.I3DeXcT3=aIMR-RFX(r[*'i)ls1_qi)Bot-Dq894>n-Gd!pqs:*68*_k%pgV3TYQ4GRL<h4U(l.W%0T0$e5)81'n^AW9iN?_o0g0:J*/JOqIuqm6(i4se55,q>e0U]%J`SWGH+jM'f=<MT+d$a<d9o4ELUs&\`+-793?.9Yic'p\/Rgf%^V7G!kN22\i`,+QB)+o+3.k3s2-*G0:hI<tN#+1X\@ahS;`0nUE3E4Df/f&1]nQjV/e$(a83Y-d/S4JR`Xad&QojLK[2_XUQb'4e:U;a'QH<WNAL-DH/:_joHp\6V'+V3b3@5uRDjs;rX8EkGY$2a/CR:hpM"&8/S3$J:%bZkTo(Ldg^h>>;1C:I+QEP/G*+HM'LW16BIQ=HKer0`$kB:B8cC,@!>,/4+^n:rX_TutGop(SIar0pXmODY:a%_M`@qM)sNd/Xbqo-iT1hjO-2g4U%l;?;OA*8:uX)Z^LjKUW[:$g+1D6;4:fmf#F2eE_m0or_n=bPPRa3pn:.Y!_?s7leG3-f@K@e$HX3k:.Pc!6I%i$(Q]?,+J:F.$K''o?.mnS7>*MSKQf0OH^'';)TN!*]>eKu)e?71h(N'W1Wo)ba8%V/Rf9c4ZPZ=WD,+c*[\4UH>0KC>5H,KV&H#DV$un-s?W5NI]RF.@=GP"Cin<X0R:JPt-q"=W&YfE,[$C%p)#?;>HSHH0F#:AuiA\-p_hiL^6aT(=.XD<LibD_mH(`L%$rmdO]f.MJ^VA7F@m%)rUIc?U]#RcQko!RgA]p+>3o5/;:-@.Ae;S0[01fL:_A>DO[`8D*5'cXQR!mD'rFt1L]l3r;Jbf4r9LQ_#b,d^FX[F*OtAhL_<Q(r:r[@AS<Zd*D0^Y,fM;A@p'GunhGY6V%P3PW:&1?#%qq/]:?reF4K`Q50]rQ9hPXcTn'B^MuGhV@pkh:GS9_UB":YmiRM7F-%;a`UnV;UjX+=eB8O]*Hrf\-O^(B@+,GVAi'o&EN8=bTg"$M%S[*'rTc?6e&BeYL[:3u.&5`e>RR8&e4o'$s1D0AZHJ@<OZiaoU+iL.ogl9XH$^6]ZL_d+=Ut4!i9Ka-F5m"HmPL*R*0]BIHQA!d/(sZ`4+eN2-W!=4(h$o$qV+NR,W9h&ckh[`Zro-(sjBE0uHg7eUp/7IEAB=NPSj\__el5aofj5Zu281):IlTajH@'ct)L`Q1*T(1Q5@6)4KC)\L0.nnqs#C#J$=WD?Qam9,qrM*4$/;Mpl14f7?n>4cC'i'Oc*BTi&s2rfRMJM1a;ZlPpW)!^=:qAM1ZUl:.2*!INBKHd*h?[;+H+p!3ZP:hh?K[-Vk\#h]fL(0Vj[$l3mUGSDj6c%!CUAQ?:iL9^($HVedA">2YK`i-t"0LU73Z=kJnpf)/'>70IA(oKX-<UF6[nPllbo3deRpk9pk8?K#Hi3nhF]OWrBrL1Cmk:rl/pbO!50s=scdDhM0r%7.a'+qN[8tlZD!u50?%#r&dSX7u8OQC"V;_H(?Scf1/g;g/0`I9#XM!iP.->'^j\$`u)gAPI]'m:'Pcrje2&UofW'>)AE,q&UWp3M+SO;NP^H4N=n:=:K]N,C%tL;ZMd)+Ya'!>I)jJk%:agBXU76u=$,qD9oIjU$T4_c2*-8uS0hD6\=rV!.Yl!-.kUDUQ=1!T@B<[H4gIe>?gdctSlr._n8;EJQ<Jcp[C$9=*<pJ2[KT^oGG+:nHQh?$d+Dg[?kEPaKSWM([4G4ROL[&?[>6\HB_gmfb1T_s)a??5nLl37kBd~>endstream
endobj
13 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1974
>>
stream
Gb!#\lVlRs&H@3/`=AN#'SIc:QCX898UuO5V@[c>VUOjQI'u#Yfp:[=-#':WHWPY034MUB,TI>1^"TrE]7PWc+'SX:@t5@/fK5fm),)Z5>/Z$7#ol]0+%Cq:9NW9jknp;@J@MKUJo!VCJD8"cR7k@N"EB(uQ:$Mh\.14J-Nk0G8[s"%U-OBK#fd#+:i8AgNVt3/)+2piiO8-&\\GDqdH8!XDQH2]lYdJl*40^cPA4:>TNlH'`%_2Xo\D77;KJ9'QV'^9[`G7o=hp7V!RHhc5V?WD;OMC>j9d5p["<j*bGN2nL:Al.<>jp@A[\P6S9a][nUM&o]Z(Mk,&Gi_ATLHP@CR0N&YTDOD2_9b[uReTcNjVF(e;.Fn]2?;Nbq:E7[@QJNBO76J5$Hq&4;?(o(\u?k#0'ai-$EHV3s`=Nj,2lmdc+3Z_4(dW.#><-kVIqG]!)iN*_i814!FS>]dD4qg38X7t5V@WX;=Il?r%@U%53k%H92j1!#_T>Xk+j[S&0pEEJJ[?R9suJ#K^[j"N,QrtM)e[KBhIS9ED+WfV_I5*WVEM:;"^V9pdPJoJmiBr)(X<Dc.`,Q@,%(+6O>S7^f'S/5KTGG*f?*)*hMs!^o8&prkbXDiTs6rV-sYuW-#,%1KKqtlp\GR"0J+[k_5'"uO3,>7\05G=Ts!S;Or?s#)YOLA2.hp($We_JX@-hj2EoUn>l+,9=pX9t1X.u:2jbKr+3=S&*.@Jh=^!^@%j`FHuR9VG@]bGF>AhoI[0[#9(Eg^5*Tk9UrhPsHN9Qe>8Ki-UjGCG+E1">adP6RQb_i/Z>BgkiGj!`0&?mg.mX!^p(C@XOUKRAUYAWmPMN3L+O\/5-F"n1h]8>`MTICV#>Y')t-\FXG,Cb!]hS@oFh/V3dET!H6-1RsDQ_U=RL$Hm<$rOtrYI5@25Ol4B0MmgkX0)aYhD!(O4r[Sk?N2OZKQRKGZ/2>jk/$n^dr+`M]"dNjeqLd",]VIhHE->D$!\n#u.UG,il!1qck]tc-JG#IDqSR$+MD:UU/\o1MH,]B4*.%K\4#.G?VcKH1CADq3!p$M3S99r.SK6')T.*Es%g4FJoAVl/@\"KS]o'-urO`_A5(M<<N*k:4422<k\<E>k+p7-c4OKcc1A1E>9?hUX(f[c8Z4,Nl7M6>TZ=4-p'B+iDOAJE:_ppnrMF?7Er[motoR,-<8`^"c$00I"bFtkj7eNX@f-tW)id+:OT[X!Li\7gnnVTuJ&>i82DNkM_p^5CB1iepp\!q_9tPNhcZ/]XSF8TU*!CcNin;p4[F[2`M^*-=?,IM$>)BAA#ufJNbJq#,B*S.Eit&2]E2)h;pWG]\!$EcQOuia@2AkcPCh\-$f2l?.FR\pUjPQIP>H5gQp/"P2i>405,)'k4#%-4\Ig3cq$1UB5l4'faO\W.;f:atemlX$no,]W$[UkC,:piZ-TnD_/qsHFD6GCiRb<\_ZT*b\\4L,b1L?KSqU">l7fkE$ZZ)F,9MUnhH(I4G0noa6bL'RIP7ap:<0.ZHQpPLWG98.\59GT`r8HT0S)sGf=QoG8DdFbJIe=O8BIOrDu'&k1]3JVGr[&O=i?8S(D_oSjH_9W97`33ShF6kj)4k`<7L:Ep].Mb"UYHHn2_@cr9N684C'N:q6m14^]&[,C<--Fb[]WD?KTRks]hmP>G:iiJkCODED37IlAePQX5irW+l,s-.DBbWq'Vjao!gjE\?sc*N7iO&7(Pn'J<t_hH4-GGDDL^38h$P@GVpS"'H'LqHjpe@d4,:R-^^,*(LR15_=="X=O^Dr(tJ=U$$(M/.-gPQQ+"!/$-?G!"5'H#`lT9cVIr2W3i^_5%8:.#3?&o/M:'*#,PA@n?%4\S4!uU?EVRLVq,E_X"D'RVB6SWar+_F<M6,Y'>0Ns0-a"D'pR8DVod-/K8K6[SA>#:I`6Ta92f@Cc=XRK3'98_r>hN^(iT*7aJ-PQ!t(h'!$bB;g]~>endstream
endobj
14 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 665
>>
stream
GauI3cYo:,*6%CB/)E#H1tOY*2SF7eW^a#>Ff!cf(GBb7*J"Wgm^BmD"qm@HbG=Q&YX$)!HdA=f%0I%ul^kF/n1hoH"U!dU+2A!k8?_MC*W6lg0"DTL8>KsaE0)>[0@\[R6nF0gGf$,Q,$G9Yc%sr-"qU<i@LBN^_o[^c-qT[>+I^8IbCfU&OdlYl6"2:,rV>c,\rE$f\P<rMp+;)S&T#.Z5rB:.Z<5(:QPb4_Ska6-A_,*A<E7u&f64Ul\E@,UI"G/faVNFLf'e\a,!BWL[R>g[6n53[75(.crO2CF?KJ60o$SZ7;Rd#=2\M:WF"&_uNi<<Js%Ra]T0fuHV\]A3LOjY,)Q3DRmJ(N[%O@ha>E6)Vme+2te#r%b./IPi7\jB-;@F^qbs(2O;sJ&;Lln&Zbm(@=_-Z7mQLK$t1Q86/aQLS+<S:Nf/81!t@;2k8VSL&p4P;dFfTpUAD-sQNG.'lk%Peo\.?EU"S!q&3N/cF>@9g!`^<E.oB=OENn9CsLiNWgG1`V,:2KaqV0O]@["7ZBplo_VA)/#$!X8q8i=o9(n1k2$f*?b-p5=B1RqS;c9c[@dT;XC"+_;_X+A@i5><^dc^S4-lB)/bq/q%:-r]^ZA]n):VC[RB.lm?!Z'Q%dV1O)J+/#f!+:KBu%GkS]*Q;ag~>endstream
endobj
xref
0 15
0000000000 65535 f
0000000061 00000 n
0000000122 00000 n
0000000229 00000 n
0000000341 00000 n
0000000418 00000 n
0000000523 00000 n
0000000728 00000 n
0000000933 00000 n
0000001138 00000 n
0000001207 00000 n
0000001493 00000 n
0000001565 00000 n
0000003442 00000 n
0000005508 00000 n
trailer
<<
/ID
[<0cbc8e901f9a8fb8899571460bcbc4ea><0cbc8e901f9a8fb8899571460bcbc4ea>]
% ReportLab generated PDF document -- digest (opensource)
/Info 10 0 R
/Root 9 0 R
/Size 15
>>
startxref
6264
%%EOF

View File

@@ -0,0 +1,240 @@
# Les 8 — Lesopdracht
## CRUD + voting werkend met Supabase
**Duur:** ~120 minuten klassikaal
---
## Doel
Aan het einde: QuickPoll volledig werkend tegen Supabase. Polls aanmaken via /create, stemmen werkt persistent, alles in database.
---
## Stap 1 — /create pagina
`app/create/page.tsx`:
```tsx
import { createPoll } from "./actions";
export default function CreatePage() {
return (
<main className="max-w-md mx-auto p-8">
<h1 className="text-2xl font-bold mb-4">Nieuwe poll</h1>
<form action={createPoll} className="space-y-4">
<input
name="title"
required
placeholder="Vraag"
className="w-full border p-2 rounded"
/>
<textarea
name="options"
required
placeholder="Opties, één per regel"
rows={4}
className="w-full border p-2 rounded"
/>
<button className="bg-blue-600 text-white px-4 py-2 rounded">
Aanmaken
</button>
</form>
</main>
);
}
```
---
## Stap 2 — Create action
`app/create/actions.ts`:
```typescript
"use server";
import { supabase } from "@/lib/supabase";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
export async function createPoll(formData: FormData) {
const title = formData.get("title") as string;
const optionsText = formData.get("options") as string;
const options = optionsText.split("\n").map(t => t.trim()).filter(Boolean);
if (!title || options.length < 2) {
throw new Error("Vul titel + min 2 opties in");
}
// Insert poll
const { data: poll, error: pollErr } = await supabase
.from("polls")
.insert({ title })
.select()
.single();
if (pollErr) throw new Error(pollErr.message);
// Insert opties
const { error: optErr } = await supabase
.from("options")
.insert(options.map(text => ({ poll_id: poll.id, text })));
if (optErr) throw new Error(optErr.message);
revalidatePath("/");
redirect(`/poll/${poll.id}`);
}
```
---
## Stap 3 — RPC function voor voting
In Supabase SQL Editor:
```sql
create or replace function increment_vote(option_id_input bigint)
returns void as $$
update options
set votes = votes + 1
where id = option_id_input;
$$ language sql;
```
Test:
```sql
select increment_vote(1);
select * from options where id = 1;
-- votes moet +1 zijn
```
---
## Stap 4 — Vote action + VoteForm
`app/poll/[id]/actions.ts`:
```typescript
"use server";
import { supabase } from "@/lib/supabase";
import { revalidatePath } from "next/cache";
export async function vote(pollId: number, optionId: number) {
const { error } = await supabase.rpc("increment_vote", {
option_id_input: optionId,
});
if (error) throw new Error(error.message);
revalidatePath(`/poll/${pollId}`);
}
```
`components/VoteForm.tsx`:
```tsx
"use client";
import { vote } from "@/app/poll/[id]/actions";
import { useFormStatus } from "react-dom";
function VoteButton({ option, pollId }) {
const { pending } = useFormStatus();
return (
<form action={vote.bind(null, pollId, option.id)}>
<button
disabled={pending}
className="w-full text-left p-3 border rounded hover:bg-gray-50 disabled:opacity-50 flex justify-between"
>
<span>{option.text}</span>
<span className="text-gray-500">{option.votes}</span>
</button>
</form>
);
}
export function VoteForm({ poll }) {
return (
<div className="space-y-2">
{poll.options.map(o => (
<VoteButton key={o.id} option={o} pollId={poll.id} />
))}
</div>
);
}
```
---
## Stap 5 — Detail-pagina updaten
```tsx
// app/poll/[id]/page.tsx
import { supabase } from "@/lib/supabase";
import { notFound } from "next/navigation";
import { VoteForm } from "@/components/VoteForm";
export default async function PollPage({
params,
}: { params: Promise<{ id: string }> }) {
const { id } = await params;
const { data: poll } = await supabase
.from("polls")
.select("*, options(*)")
.eq("id", Number(id))
.single();
if (!poll) notFound();
return (
<main className="max-w-md mx-auto p-8">
<h1 className="text-2xl font-bold mb-4">{poll.title}</h1>
<VoteForm poll={poll} />
</main>
);
}
```
---
## Stap 6 — Test
1. Open `/create` → maak een nieuwe poll
2. Wordt geredirect naar `/poll/[nieuw-id]`
3. Klik op een optie → vote-count gaat omhoog
4. Refresh → vote blijft (persistent!)
5. Open Supabase Table Editor → zie de vote in DB
---
## Eisen
- [ ] Polls aanmaken werkt via /create
- [ ] Stemmen werkt en persistent
- [ ] Server actions met Supabase
- [ ] RPC function `increment_vote` bestaat
- [ ] Geen errors in console
- [ ] Vote-count update direct na klik (revalidatePath werkt)
---
## Bonus
- **Optimistic UI** — `useOptimistic` voor instant vote-feedback
- **Empty state** — als geen polls: mooie CTA naar /create
- **Disable vote per session** — sla in localStorage op wie heeft gestemd
- **Total votes** — toon onderaan totaal aantal stemmen
---
## Veelvoorkomende problemen
| Probleem | Oplossing |
|----------|-----------|
| "function increment_vote does not exist" | RPC nog niet aangemaakt — Stap 3 |
| Vote-count update niet | `revalidatePath` ontbreekt of verkeerde path |
| Form submit doet niets | `"use server"` mist in actions.ts |
| Foreign key error op options | Poll moet eerst inserten, dan opties |
---
## Klaar?
Volgende les: Supabase Auth — gebruikers laten inloggen.

View File

@@ -2,7 +2,7 @@
%<25><><EFBFBD><EFBFBD> ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 3 0 R /F3 5 0 R /F4 6 0 R /F5 9 0 R /F6 19 0 R
/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 9 0 R
>>
endobj
2 0 obj
@@ -17,7 +17,12 @@ endobj
endobj
4 0 obj
<<
/Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
>>
endobj
5 0 obj
<<
/Contents 15 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
@@ -25,19 +30,19 @@ endobj
/Type /Page
>>
endobj
5 0 obj
<<
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
>>
endobj
6 0 obj
<<
/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
7 0 obj
<<
/Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
@@ -47,7 +52,7 @@ endobj
endobj
8 0 obj
<<
/Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
@@ -57,12 +62,12 @@ endobj
endobj
9 0 obj
<<
/BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font
/BaseFont /Symbol /Name /F4 /Subtype /Type1 /Type /Font
>>
endobj
10 0 obj
<<
/Contents 28 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
@@ -72,7 +77,7 @@ endobj
endobj
11 0 obj
<<
/Contents 29 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
@@ -82,265 +87,95 @@ endobj
endobj
12 0 obj
<<
/Contents 30 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/PageMode /UseNone /Pages 14 0 R /Type /Catalog
>>
endobj
13 0 obj
<<
/Contents 31 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Author (NOVI Hogeschool Utrecht) /CreationDate (D:20260607080655+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260607080655+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title (Lesopdracht) /Trapped /False
>>
endobj
14 0 obj
<<
/Contents 32 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Count 6 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 10 0 R 11 0 R ] /Type /Pages
>>
endobj
15 0 obj
<<
/Contents 33 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1129
>>
stream
Gatm:9lo&I&A@[:lqpJ50Kt;rgsW]M1QuP5=NRNYPXZp!r/aLmaf3%g$^(Q?fs3J1/WDjq(2r)7]j6Ep`>@i)ZP)2_-!X\0?lYJ>JYaWGjTkR'RG9*A/$;eW6l7C)#@^-sK4^BJ+;Ib>>6]gs@WVsV@Dj!uJE&YlR>/`!f2i7\U(u3*"_*iu7Qi^aLuKCQVaN"GO3`mb9V?$T)VH:YiJh4^_+%96<MY:'W?j)g=T%^PQhTur^%-$KY3Q-QGE'r"*W3meL:?X1dbjqrhYQ@^=T/EG=!>Bg1mO:rOm5<\&&,0T[uH;2+5JEM*3^=%2-+^XUA.8R#tD:e!iu?3M%bU+as>MXW%3Q'+"ZAMKq2A[PnACi<feWtJMBHhPUr>qeeA^b=bpaMfc_glM^qpcgFeXD=^7X6)P*%&#t5a9IZEsY^T`Tu9@aDuZ%O"4"`!46%aj%L?o@pJm9Cd0ct9GOCI/JqB%"ul(_r7RQ(U9(7."uJ:2"`Ap;>SdQm@hL_^8e@iK@@1NdXi[fAQUc/'O\RH_@Y=fH2pH@S\d3\,_L&.FiT[?gOcK\2,KS2F'JC=?dV?PK9%lc2n4RIeW*u-2\2GFdH/[pu\'*YAU'+*Sg"imVg_RB,^tnFVlR[+S1-9geuN:E0nq#HX@.k7=3$:cE[=n$Gm3A:sADmS/u@F+<_G@"R1^#ieuR(3?UItA^O"6qmkAG&:97tW6-nt^fA(KDI&U\<I6J=>(aO[_Rj+&mb6i(S-shBikuCV5lP?VYDX-Aa@"q4;=Gb1TcNLH%XX\^gKh:;ORDrnD02nEG]=Vfkp+eT!NCkU%kkmt^Z"1]^AAA(O=E=K4q8XD3<=qG@Lm_XLr_m9<6eW<?u`a32+'*r=tJT=L'B'tC=i7g2MGr$I,eIOZKMr<`eh]>mA0SXWu1?e:Q#;q.N5%rs7u.q?.Su`8ngm.17mu&5^pr)Y(AM@/YAg0hSAe:cScm2U;4TG'`L"_7U,''S^B:t6<"?<<MdT]\Bc1#A;tf(Igp8Xb7YW/ff3dafJIH*>?1D9*29p(=+I&R!'EUt2gCHUFgCdEiY_0[`P:Zm(:X0A)0Nd(s69,;;5*65a(`SO`uOERgG.Rhk4>Ba^E<@IGWJ+\+41jC+o~>endstream
endobj
16 0 obj
<<
/Contents 34 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1269
>>
stream
Gatm:ac>+F&A@Zc$9Dm[Yh=@^P8OJJ15Gs@ll`T0\kl:?8[t04/K'3:pCp2UUu_&"!MYQOX6[IN<Q1tI5k2sbcXd1Io*g4t#)pH9%87B@ZZkonbkp`=Y.9Z%Lp0j3*(VLC#8A+1"f7%cH-!d!6`cCm/L/i$(-("c_[I4heuq1?`+Wne"CdeI<e"U4Luo\V,uIj$fCgS?[[%^BI8YhUgD>J#%X'm4LFORC9Gn#?"Ju^u5J;d.Z]3]m[ojKaa0K[-D$b:/%D6ro^Uc'Nc>m"A_!E_A]rDACTMeX]KJ]$gn(^+M=%1U>I>Ben1]fi@q#e<T7a_,Z9i=HZ;@L8-&Oop%d7)m!F`m'q%t.'[_Y"HQ:E%]n[p+bRBk_G:06K"rKM$!6/,$Vgl#gc.186$`1`ie+@MD<1$ne>j2g#J='nkk%`#^/Cg;2[R#GXH6d\FLC(k6X2:\Oa$qQEP1lSZ4P5MM8)pB&2YB.:*`X;D'l,U$f*K4#jb>3[GH]-P^[&ftIa\>XKkZ8dRd=;P*A',!^VEgNX"a\U6\6&17&Y7q0R&\l)=LPfakg0AX<L3Mb1;&,G%Y0r%3IVE@])`OD7DrC.s@W'S_dPco3G=PdN.En\77KrrF\N3joga:E$Kk27kpCC-\mNtMIoFHDVK&l,c<LH/@gWAan</'4_ks,i(bD)[d4-i&p`j!b:dU-N>_Cp9sH2Xsge\OP3Y.kFSClCkf63U:TU30K^d)PA=Yn,pEOFEfl9BUf,#tG8S-M=de7tt<<=655Ya5#`T>o3X=mGW8#lm<qWN0DG;eW7RqY',M'NS%-$,Rrk#E?=/6\*.R.geBsI;7%4g^oSghlcg0i^lJ_M?/[rPa9i'h`5'N[<U%Z.`fQ0,.^YNLK997i/XmAu)2pV?,)l)KXl<GGbdC*tG[u)H@uilG/0pNeHfO";KQ0XOUL+GOH^*L_5JUMP<khSKQ@nrO(QV-tL/:7POd7$]GE;</`0`$k[(;Rs5=@LG=J,V/Pd/VlV@d'$Gu9i<G#=P@)h/H$cI\:I;b[bV?&=9qkY'"3%Q'48Brq?_>(1Vl2c6#3J%P>a@qD++`@f+6XkF@rCkGn.4"OZ'?+WSM";Z:!H#ImGe.m>3Na\3Va/5'Nr+;a]SZh_[Vm2'^-PGcj3$I;"o)&]^]?V@%S/V]*Yjp?3_**g-c#C^ma`I;k)<JZgOfIf0Vdb.Lnp)*4T_1&m\=+CK%7<9<0Np7FIX2_JQpu?B[,'e*#`s)aE&Q`r@kdlO8d'D=!)OAte,~>endstream
endobj
17 0 obj
<<
/Contents 35 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1784
>>
stream
Gb!#[gN)%,&:N_CCd!6/F+F<&!5YPS[(1GHR7s),C7[8G0G5om6]h]^fkDK,HPZg'Z9=r<LU<46,XLAT_.%V.^jtF2ec1Ob_"/F;Nu9V]ZVt7`#ai;[=0pgX5e,g9O?c-,_jCO_6hc.P($$JP;)++LBGqI'#nWO;X^_e[a$gSuTJUWa+CIGY73aC7BI9!F2o^V@EK6n"O\3UEa#Eq'UDFToYX=lYLLAbe23[<%6U<,aObDC+-GTNYrWI[%<i0&j'h&=Vg<qOt/Bg,8i0P+%C!KFRCeT*WZd1=Pi!^#ZKqq+k,2*3KD5q'O/<^S-9sRC_"Mt2\>P)B_U3K=*L.$\<6gk85;&1[(;0V]9FtO-KVh@]ZO's&b..Zfng9NtWl3?rVh&7\."c\6g]'Zg0]!bGUKIJ?bW4"9i,`It>(-IOChl1,4[3/HKO9LS2=q=rg*fTg$('3gEAGFMkD8u=Vl#.BS=]!/%qt_V2*et<Y0h[@@U11??0o7pN$:5I>Wf_m;Z\*++TJGW>.1`$*^=_7$.<.'ZX2h(&9i5*(KPJ+j4s^JT"fGq:L4c+r=o)jd2NNHIORPf@?-q"N;[c4OJ`c*qS`\%>\k6dBjJ/ZIo.jn/;9tFW>pe.88aP+_p&_"4S1KST:nf;KV\c5FPd*/b^=L;flE>R9VqZUXkej,ON^](Ao>t]DY$WM6q%8XV]D3%DmO,k]8X'X3g&Wa^]WtpDRi-GX/Ke164.dMBbm0&m<)D7'buZ-rj>nQKco]n!`pp3Dkc1*fR[<cS&Rf\d/oNOt"pX3\[E2<ZANnGf!a-n?q#j8O"&%"hH9R`=@In3%=]<Tnc`rq,,bH0<&Wh5R7f-8M$Vb<U>*eD%bU5W"2h1_UOsHI;<u=[s!PcOhKo3C@#6_8DAT7a]\U[am=Wm`spY3ooUrhO<XOA/6D9#V;]'5:#MIV(mZmC)Wd[P7)b\g3(8r94GBHX3O36AF3=P.$Rm`/sD'8a\TB9=iU=U2PXrWnIP[=:FH?qNV:j<@04=&qdA7#K&fMp@s5V)3MG!P3e$)6QB@"80R\H>`>rAWohiUC`SuNK+2O.[+<&Ea^s`;IGd@Cgaom]ZH*O3O6kfCD'-0%-+X5+bnp7Qtfri[Ag0:A]E[HD@dD>pBLntdViLE"2i1FIM947o"i2NU!\Mq,5dpD^^WAiW$?1J6XQM[""5_h6>M$+*njlneYfR%cbP6koBh<TksLi6b=>CD]lHPUeBnmfMH]`_f$VhB[Uo)Lm_"DY[tl`d,C:/kqN1<Wf^J6ikdfpuC(=9b-Vlf0^NIjM+/dC3e&0AK2-1kiZ.c72\f+S..$*[5</nA2TXsHn=1]!1T_NQYVoL4#COs`Gofm_7P7<1Of)G4%7DG+[(Ia11(3=\Tn?%YZ<]c8Us/o93ScUB'lAm&FKp*M5[:8IX>?#gie7,kF>@k=<1D-\f?='E%Q*o<baQqK4TT4>DNS;Brl54Up:0r,TS\4AoBFdRZ>MiRimh??eoDh7S1n-%!Qp,K;*+,jCDEhP$R'sq@/btLjS#qB?.3>)I=NT8G+f2Hu&d?d1OY31=4$:/sM87?kDO*.]?g>W6p.jGBN-.-gS9FMULVW=X2D38`*c@*`/,hS"gnSC"*^Z1RX"BW-W4le<`[V73?X7-r3uqt2Z?JjRfH7R$#A77'^>\=9nmV)\'Y#,I?1O[?p745K?&M@im\*:fY(cRW[(#_AcaLa$oLeI>U9XT4Bar2eIp-[7."cbUpP@2:O.6&L(RQrg)>p%ScH!fOa_9b1rC.%.5D6e!4o~>endstream
endobj
18 0 obj
<<
/Contents 36 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1725
>>
stream
Gau`S?#SIU'Rf_Z\1mX7F>6Kf,UI#AYn_,[!_(^L?=2igPpP/3-;1?a-OgLapK^Cs/>ZL:%E2ouEHFX@H[%c8Xr1&`ZheUM"aI;&fbFV/@Bg"`Lk*G`GdSB:)A0-^.jP\HUQ3ZOpl9VcYo0A\'i@0h)0jXWSh!'NN-Lr_!QTVkb?QGPXIkIh&6D`\'0nZ,Q)D@Kmh!Gu\e[[`jkntQo(*8QT;\%rdVM)QL+?AQW".>iKJMda=DVF:p8@YgiQ#c0bO@R9')8jaFEh*-P&hFgGRZ>!ND?ca(MBuI!uB4AK-$tQPXn<S6dRd'bjq\<3hU]5-;FXS4cl9jMFSB">A>cl`04/.oH+TaNrfJrSBe8k:3@h,SYjL^<KMiHr4gQ-%7++8=UO';='&P0*O'gV%i%5k"/j!qA[SSlPlls`f7^W*@KVf:cY%Nh,dZCfkkA6?]d-T\]<1D!hD;^Ho8js@laWPF5o=1I_U@\_S*66f).BWZ0%'+)FsL>%.D*lkN.a^G`fmC&9gu"RDVsFof7]pE`fQCfW2cOPRj?4si#fe';U(qr6"`K^dmZ$$`:^e"D0c8Y-XYhgT#`1%d;a$tT2'J(2]Q+al5hbMVIWApr484Dn_.mF-.OA,B3\kGn[?L9\sCCK;F@FA)dSE;HajBnIG?']X6Rip`7mC).bI,!bC`fF+9u!bfbVTbc]WN14.<:EbU(c8rXcH`2aJ'H6)EHBeTD+flHe!3`4iRq;@Kmp2:oTMjZ=;RhePu_5M+25nh(A[]h=i<]"qu^:/%4nN\2I1D-+;.LFbAC:R:)[llRU.`T0R@h/-BtK\.g;TXlPW!m`f\i&6Cl/t/TW_rYDKVdZ:.3itR_*oh=2(Zc;R4HHsXTI'FXN]tBq^8ikIk3%d-8XC:&X9CX9cR])5ZK^:ZICt<rUco_eVReCc>=eE=]W*R.%C4Mq)/QYpfl;i6E:,l\8rh/2*Zcna@0%r-*uh3UB&@.inBpOpphfL12IVr2FTV8tKf%#Xlr-Su3BKhlb38#<Tq`%&i&gB,0;FPLl9aj\W$AQ8<%"CMQ<:hroA<]0LisT*LisP[KVBhYs075dB+W+[lm/95&n;,_ZK*]U:aOUfm7_HmjR^1mWtcLb0e%N/6q1dcS8_N-G%Kj2cj2[lZE4S#q\Wu185&8ofV,$RrD#:G-,8)4<L,6bqc7jbU$4`c-T3:2/s_LTnt'1M3fW-@;_."gE6F*GUJ^=BmPl[a[4>.>.Ea's&aD('.I-"5IC@&EHuDnQ<cK$0-g<6TN[HqQ+\3S)cOS8Q/f[<?8d"bPE`GWTZAi?;F"2P6!2?t3<f)k!q_h=W$OGdgIld0.PFsJa#$X54hbMdJ.]DjI4&,@YJpck!.Ou]K5`tH^84RWiiTtNgg.XFoE&X&hj)C.B5o<[:ZZ)S%#jR<h#tr4(k7NPk2P>J$k!AikhZhq65$ZBJRg%#9U`0@>@/WXG+_XYBa.405s72"qPc/0)TBB@@B\Q;(;8h6'_onGs6JJ[BQj7#9O26'R.@^=dp9Z"03*m$s_R-M/#LbM*&V\'6p>d"'2gSp-UA1UX>>/A%Vfu''[Y4:2nHtp1-qI8G-.rLuEg"9:\Wt[X!NW>XPA7t,qJO$n:d>MmQJg;eQ'ZdVe_HWs-kGJro3.`Z,X$S:C'tM=As9LY"SQsC/EYm.hh2A-RtheVeh-YH5HSMge,#oDJiK1\bqK!#DFVe@hBW<#^Aqs3.,b~>endstream
endobj
19 0 obj
<<
/BaseFont /ZapfDingbats /Name /F6 /Subtype /Type1 /Type /Font
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1891
>>
stream
GauHKD0+Gi%0#[%JbkRoX!s1*,UuH6>IS51Xk0GPf6sTE4'JL%20s6g3m!]2Iin<c3/JBJ\\u57VMGJm!tYG]R/!DpIm4!Z2$)`n!bF&g!9JmOj=S$9%)*5XF-t-f+I4]5NredPr"%6;+9pRDNlO6h_K:WR3H.9@&=rlVEir&@8/3]L#8E![R',@4"LT9/glT"$_\fE9`-*,=;nfP5jQ:a+WN8HCb;Y%3%U(mCTN[kQe95\r6nir]rpq*(,?_%j5=q"LrmIe::Gb`_F5`HEn=)I;@Breq*_a;aA3X/B!Tga]Cl>pW6/S[n=j9mu!$06o&505h+<Q]a)T?-MC#!`"iL_2$#W8UE+@XOf8TdeU!')@L`cVfd!I*@_hI\>ZE+.m\m8=T"LR?k=].9W4it%S9bI!+6N[UQh2*jnDePt1el'6T6".BrmC4Cm=8mEN#O3ImPCc2"jZSa&I+-!+^GjA$"eK::iMG20"A\a9M$bRZn9d6U-k_./)*i$p[-7n.s;$>)s5d"/-.LAK&9/-B\XQ37kSR("lo`i9%AiM;n*^m%SeSkiJH6m2Z;fDnu1l5W8ZOmBtUL##@e,sIG2p8mp)(58/=i^+<1KG=GLuhdDPWD@p?;R6B9fFX%S7m&0Uf#015J`,[MKNO\:OB?$C%G,RhQhuHaI$*KTIpQRk%Z'kTa$q`)uHjAa+!F`*+K]P^o6M]Z:?W\V"P+&,uY[mc[/&RPAo"2L!8'JE_qW6^bHH5AErXsK)#FX3Xt'p>ePfkkoTKL6%pF>T$>Ch5Dc_:h&qd0$]sO,d$:%@-E6;BgCnr:BJ-\TJ35hRJ9<pG+?I.`/JTH0aTF[H%<Jmm38Nm4[i$5MQabtB$C.e,@/i54X#s_AFL49gl\FJE)?oM1U:qjG0HWK6GO&q>dci0I:\T0TQlr!dFA9VCKpXI@]fpbA92*t0[V%)/H:/dc<Y-fi3dR+@Ko&VJ_g<g'/1aXu/FVGLV:Dk32U53'Wq8?3;;l\7a!7)^_&<dn,8nGXLGI'0a[j)^7e1#95*"b:?&[lK-a4MIiQLVe[S(X>BS22P-a\f3Z07/"70nesf&KmG,5uE&LG(<%IY\JUW3-Vi'AB4<gVg@%d8e\\U)`DdJTh8e%uu>Ygg[>g3](k$HDDD&qi0oB;Z2`Z5)YTOgVGU-$ZPIj[r/tshJCh*7s-B!<g[Y]Nc5[^L)j;g@\Z_&Y4,:C@SBauY8PsBhTS/Wn;_[uG[,Gem%@t<2H_iueab[E=M#Hp)hUf-dU5]81_Inu3C),`DShY]XeCDJmrSl2pF?tGJY)W9El5uf;^JiOQ>=$.]oQO0DTZd.@r(`?+t6;RTnYO'lZ6':l(,!8N:eT8Z$W_:4H-DWPB<s9WDYSaE8]7X9:=Y4Y8i?*T>ro,D=NuXMT=:24Dm#6rnIjo&]-cMi"S7R&]D>%WSNcr$u=AFa81k@8Z<kinB.uj64/&R;YWCG@1OUEUKXHC4*_YX0FNMO$bYGWn9U<&RDu5rfsUOeaiC1'@Gc]tLTs^@OAGQA5*<0J_<ZB>PB;##rkel.X-+iHc+gs'@J#<aj-pOp>T9lcGW347KeU\c2Z.4rH&XUugtt%=ZT9R[kSn3^,K+t%?2%)=/P9hO"mtO-.I:F"CN8OY5fu'LVjIVM.Qu=$(.dY4OP>s;VrK/rYgp.fLS(r2U;f(gdN7*ocIpLl3S3QMh)UalW>&l_J]o67\iIgcb0c4skXV/DFm[hZF6>_.s4Ue>2d:A8@tJ/pofm`$\M<<lE%8e,[B2re:IdaPCZc!'T(d)eVFd6<oeaE%-fMMl5%38mGhMoJ:)*"/?LtF7eDhC9jo`eKPc?MW#5PT8WDC[sHV9R9Z^Xd+(DkI\]8>iR(Y)%>-EiSWSSd!`KDttDD'B\~>endstream
endobj
20 0 obj
<<
/Contents 37 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
21 0 obj
<<
/Contents 38 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
22 0 obj
<<
/PageMode /UseNone /Pages 24 0 R /Type /Catalog
>>
endobj
23 0 obj
<<
/Author (\(anonymous\)) /CreationDate (D:20260407143958+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260407143958+02'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
>>
endobj
24 0 obj
<<
/Count 14 /Kids [ 4 0 R 7 0 R 8 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R
17 0 R 18 0 R 20 0 R 21 0 R ] /Type /Pages
>>
endobj
25 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 952
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1232
>>
stream
Gatm:9iKe#&A@sBCi?#<#YVI>WA?]aThlS0Rc;a'(LrB]`3C?'T``'D/(lXP#/c#QbAqd6]C5.9-59^4;Yq=b!5=2,GX?s:#k*:i`.RO\^4jk\Trk6=Lp*2_L%5KaJ\Z]Zj@'<q3esPaTpf%?FYF3j&s"d!U<2]RXN]b$gaC6E$6?td7R&Q0ces.)eZ8JZ-o/;@/:aKO\Bqh0dTM#!i=*Sa0](ZAPtqUA':_TcLPt>;A&m;kcN6lBiR6hF!E%W7?@_#n=;Z:K6"[AU7YG`WCp@7/(!$R[/rMKaUA2Ij&8Z^.Jq-bYo0<dP&5mW\Lk3-:q%S"U],3R3XG7qf80GSU_0)![=[)hY(Ie!&Gna7t[4\6/BVdd-gKTD@#U'I[q(N5W3eug?Xc/`Y.1M)@Z>DUeVI1o%D?0<N#G]&FRR<gA1i-i\<?7@o:_Zp98oR3M#`HP6kAuut^lPcp_k48T>U8%u7lBK;U(#J_C$7+=!D9^kB6Q3[l=bb1>$%\0OcCO%a*dD859?t\P27fU$<a(H#OXb0hbpIg.r)XWA=0dFV[q8lL/=Yl9qCM=\oK@NK/"f5O%UY.ck7Br4B2%7^T1s<D;=1E]%VAQD.jD@Z/8Qb#].kO,$s`/j>M0/\p7/=3n$*:K#>+H;6?ONVJ.+=%1TcoE-.,G:C:Cr)c.K&pCt#*liE7)N5Ecu9=W6(q-<)A#CAh8D!#M=l#]qkI,E#6n7Ea+4FtU8NT\'6/Ak5*@*>R;l+#'=3W8.9SiK1g!t'4T^J>joi1H3C2W_gX\FPIjY%R/X\?^j>oaQ/T0mL!B^q5SWH$oeO)8fuuA2,P&2cpLg1LN?/*-Oe4[h>Qe1W24()Q)9uX!pp`IC;7$ZYq62SYA_qfXL-r045$/P%pBCkud++ISi:hbG]2rZOIF>Dj+1g*UcR'_ZFsukPUOhm[f^=U":[0$TS.eIO$@u~>endstream
endobj
26 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1229
>>
stream
Gau0BD0+\p&H9tYf\@ip;iKfsCbk63\`VU>BjM:tQRNqE(aTH(aX7IZ]:8`m8hpm0K>Y54?n;gpXe+?sSm<SFeJFWhS-#5ST_TW0EhIUaaKn"mFl9?&qcH2nbJ:B7aGCJ8r0E&2+B&*dA'51KQKNn^L:/$]?q%6tJ@MX/T4m>R?E0$)^bJ@CCBs,h'9W?16^Pks#5rk.;o0Y'&k4u19_Ju-Tf7PZ>E.`JI5g,)4`dOkCbuElV1A],CkWqHqRR0h.063Zj<QR4]+Sb,/-LCABu)gQ,u,(>"E\8o*o`^V`Z#'.GJN_U33#Bf_!ql(b=naJ69l0G;MGjX%)scDf/"=@YBZ3q-MW84&sV4B/"ACFgD)F=p+"'9d`$q5otrF?bD5t`'a8b2oO*)I0ed9oqWERH'rl,DZ6fjI^,>(S%Gi[gG9JfJ,83/^;AH>`!;r'7dbcTo)O%g#Qqjk(VHZl@I=7,F8Rt*r&!1Yt'O:VNa(#F=92gCUK!><E>OX-T$D^L_<rXkTb;CJbaGH8tENgCX*sVV>Y>`gBN6S?[9M&!r*".XZ$)s"D5<p`L^1M)qbp?H#6\bI+(f.sfBs8NQ\jb9,8pH;Y`KS_K*AD)oj!+VWF,eo#ImNW4`:dL/9#Pnj'k0C#$7`?5MQA@"r2lc"SGgtW>htoncJK)B2chB)-f),Fc%jU7=NW152k(IE]5K6P[S"PD0fSXg"Di7$EcH@Zq!IG:A$[75c5KXPWA18<<61Tcg0F;K&;:OYZIgcWW;f0:8/G#)V)sl-TrVAj:o0D(4QKV'b[cg"h<",NS6VUhE.L=("7GF71VG$7XjgD:lQrS%K%@Y9jVFkBMBYfo;H<rLT(BO>9'GcD03U-g,cV4"EJ*bGU_>fDUuR4`PR^DDY,Lgn@R74Dmn=&G&T.bJiQ]@sn`K%,2F]ag_75<3ROq@i_=9=BrVBE,7CpZ2WA5fGDHb[N*?Y4Kh7H;d+"TSI&!&1ScO'>?GH[Zdmo*7uBXkL_2j3'/,?9T(BJ)0*VWo_n@2$gKF1'38jqLHOWqC/)*l_<N&m(.pnm6*XTU*9>Hiu):_1KLfWRo!k*"t#EJmYsKNiG"\B'GD5UMV>"B-`h.X)=D"U"]$;_a5WD!L>fAH)<aeD7DD]s89K<q7':bbCGI%s!sm=j^_3(:6LCgZ-9a(q+b#K9[7,OqUoQ>,5)BVC]&gZ+OIgi_!R*"OqKnq;EQ7A%3*gr"!`SM-i~>endstream
endobj
27 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 746
>>
stream
Gasal;,<]I&:VB$n^ZCsg31X@a$G]%@^J>K`9QmBR$\%Hh",F"?-orQs*GQB'0X$2Q7uinB(h^4k2UFJinZOt!f%(GIH06,P&'Q;"\;C.S;cl*]_;gt(<0\)0b%U3j"Ro]p=KT?a':_rZ36f,_-K+YVISDhrqqK#"e;nFC;Oh_'IfE<Q:l"3-r$gh+HSHF8lHOpB'6)%DH'Y0JgthE5Ut!H8u0<8_c]EC(WdZ=T"WkDYBJJ,aG%/r9;-ES6(@.!QZ]:>L]OIWHf'6C)NCg_YL?VmcL#q3MU6F::r/kcEr?iEp>TW$-?pB43-;&qJ5*)&Oi#/;I=l4M+r^aS:SA)MHelZe8`kKB11.<Q,C5:/9Tu\3QeJ=<(*]NFaAS^HdY5otI9G$!=g_J#:02XD\:a3nD-#h$1.Nf%WTq=gEd.<1<&[tu9;B^dh1\Zo,79%5>7A,uZ:<%6(NR*QMY(j3%*%=E5aj0@lfk[X@$tlWL2+*W)'&;B4npquLE!P#gBnJ\=RH+G4<Et+4VX).G[2Cl>Wh4RkH.o(J@f+Ur9ei=gYNsuDgIq#>uJ'CL8hSj2%[XMWtad\f^BJ7AuuGHAXC]fPP4El^n7;Yr9[]IJ8s5Q7-A3^EiXol.>1nWk6:"]1f#`9M<B1-XmL5,Ec/9hYBA(gK<+L0JD;RFVA$2\O$+P9H#YpaX["dXCfq`W^>dW;^(<V@B`[:\+?P>.=.BQWV1kf#UEcK:]QY=!0_u%8a\rN~>endstream
endobj
28 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1400
>>
stream
Gb!SlD,91]&H88.1$+Tba2[FhVc?_og>968*X>QW1tB]f-HUjLL\7*O"T8#>Y&0=u65"UH6j\a7h-&(Jo?9<<i*b#lS+h"/E70O0NuYY3r@r8PH-h$O5P.%h*Ssm&%LZ_njq.A4j)GXZ3SJ(?i.R[4b`-EtG(@Q7rW,%Dcoq2^S,S@O38bViqY`QZVhc3M4ZH/8!a1[[@,O!f>ZC<*R$7m.'hX&=+nRF]J#!2C8?\qCipKE8CS#gQ?#s@71c]Rs!95ujo=nSm"KYr\Qm?X-@/T;_lSDQgL><Gqb#I&1[C<JMMR#pR;I&'dcJTD1W(%%OZmlV630]]<;BYPj)9rT"J4.Oj;)7oL>XEjXXP,e=`rN@2#R#-T5%t.k2Xm%;`7r<0f?nYChKWF#,;Qo;W+6AJj#(,W'Q\gR@3cNqYuF:Yg*'dhYCs7Ee(^4nhb`/Tq#gtBO\Z:.TW`^I2a[a;4sIF76K'/b`<Zp4r=>eJ@$h[1=.$n,+M19U9]S-4Q=9dC%Z0b4fo@"f,fYn2#"2-!lV<&PfCPUqb_OLb('f""H1:T$`8tqXl!H+7=[^<GNBe\X*#ZNW9i5EECQ)PT[QuHVo0Oq:KsE;THPjq8"p_6a/ff=VcnH44@"23ffn8[9?+$&0fbcm\Rnr.WK$',8aredVXd.+plNEI_UE!Bg_n'C9-:nCJ0aMj6!QBGALtqK,ie[`j^luAX:&(W;4Xh1m$KEU3PpgZTc+aKr7"m&:,]%m-?hF'\J(1+*L"l!&Gi!2_;@oND7"G`Q8<3kU@Gle?D8a.%HZV-k#Ns5,@s:lN6+dPThZ+5Z0^qDTk'4U7a-l=K[N?Fg\m<di4h.FJ'p.-m9hlM#;n1-OPc@#$CR=H4nhdC<\]6D+EjF%GQ8#NgAr.-[3+T)PCId9>>a<"1V7&[WmXg"4@/M(m9hNV`<O?f=VKFYuNWt9G[s!B;OrT^lO?F5R]IYgKjss8K&lg6!B\6NP;-%CgAZrMgg';hGXl]0H3rXV+lasU5>ISb(!-L;(pY4/9A+rWSaN<Gtk`LmE;b/uaL`:ZD>=7]J`Ma#e2&i9;:/Kl/N3[71<H6UJq1kueD/U(5Oo80\Ba?BTR#8/a.r;a$RN(l!18XNWN#uN9QU\Vi)]2nFOVf+O+dZ/p%0=Mi0G^(NZ&E-*U\,k.a<qjo11$EuXSOqKVi&od=B6;66>D\k23RMqmhXU0JU*mf*sBXCnJ;k/RmNfdUSZ[L.%G!4oeT=/"RZh_D8/ub=f,P-s1>D%1G%b+R,iVX%<n<qV`0aE#nT=IWSF![37k2$0Ys9OIG[;C7WE+A<X9ud`f0obI*kb7k:$^nLAOo/1b$O`,<;C'd^T"hrVg<K36<))Srj:)WuXemY$9(pjUr.pb]!M]nZ`1e^B!-67K*~>endstream
endobj
29 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 285
>>
stream
GapWf9hWDY&A@g>]]89#G1&9+-UC]C]ne]:-+:/6V+n74K<W,Il/FHP%.=ja:s.-rG8'K0E;)[A%<hg&WePl@ZR\cSr@<k.`bJ.[RmrMt<d[67o%rT=JMNM@A>$:]KuNsq8ESGR\Q$C>;Bco_9(Z/hHQ0Yj1%C-mEQUBS]KG+0i/)_IKq*J(Ekj>HJhBeI"qDSmNl'_eiN`qRFK9Y)i/VccfQeS$a@V&3X]m'cT\ig.M/coC)(CU+Jip.0bfPA1Kb;d'/DUi_PI`*_(HuA+quMG%;mQ~>endstream
endobj
30 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1320
>>
stream
Gau0CD0+]+%0"PUd.$.e]@a=lN8^4#kH6JiBdQOnVI)q[/@GOcCp.cj%V.?mpM(MgMZ\t-84/.)b=[(+Xn2l'D>GsX*@(V,7aV""!HV[+"kIh-0Y3"27ZB&1[b9oUN]1n^%/RZO_ZntJjQO#3H>^LP"/k1g3s-:h5tCs+S2EhbgG:WXaFjr(0ql@c_>4`uL<^>oMBiiaV@$6MZB3O]!MdspHE0@06(_XP=D&]]CXW`Fl<4A.#&>LF/2PTF%$I(]4sQ/#%Rm2OY/pBkk6Uf+;4!@MeBgO8?k4^LkmTA>.p*&p@d:aI,)["DM;8eYLb`&=d>3P@]^1qCnB@/@lhH4kDF8ieh(f#T1N**0m5r9CTJ478Fo/t\XHi;n3\"LRfXaHGJ9%!HnO3oZ*OZ4@!'s[2=GM5>rmUB$FAO0U*7=nMU2=]c#E5=po>`]?4=mmC:rNiOZq7=>k+'I!&ld2"/U4(k\qVkbg[Y$OFo6eC!iW8OrmGb3Y\5uuYMJrb:gGMM.G2B6n+o2f-S]Re5"L>;DiN_n9Qo!LAEud0^jdep&HtNOG_-g5>7nn9XC*MH!mMfjEAVCopb^kIGKmDKm(\S/qouhhQ\r5KpIDZ+NP?r:[OSaDP./SXHX]GYQUWgM.5*(s-C6D<dQg5FKhio/><7OLCO?.Y4+lk3PtN5t._X($Es3nE>6hQH`T3_s6rh<m%f%R@LWao--&`lfLj>TLn-#q`$[Z'q0dM-\05Pi(=%f#!8jI!8c*bLap%0?62J;p,'W&V5OHHM5Ps#_!#g&lOa8/b'@5L?8PPd[KCX13qA5:'Jiq08($7&NADLRMP8ffKH:>u=lYMFrDTMcgH\qe_]6fTdm@M.Cf'AULe*Sa%b/CkCp,;LhkRe$Vd3FI-P"100;mcun2A.$=JGXaQ"ko6Y-X,Zu0p$gLlD4AI,5$f*8:)'j)or`47d!@Pk`u!coeN(aI1jg%*qJuIMa]d5&QnE`&Z?Oo2J##_QhQHs:IEVQ94Z[b7N$D'F>:bN"1R%oG'*5n%bIe#ip\i@Ulgo)I43>CC9Bn>I[nA(9lNdI7`GZ*P.Ke`)RmVf(3nA_2h_RWc4"=<m)<OqrNG):V;edO]T"^I6b>6Te0#ll7f8!!5%V\+"-7Id''DPI5Y$hha=#*B\28t7=2'6_+rqi=OEiWjGF_^-mNZ2P;`n$>f8?a!R#4(A"6j^im^P"p:MO<h?60q,NMZE):eZkAUaX,33C;2:J1O,f>3Y0r_-+*!FQiCjdRHP_S&u<mu*7Cp0(-@efNr*YD.7]pKPGfIF?CM4kniWL4(NXdBeZMh:j'V9>gdM~>endstream
endobj
31 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 729
>>
stream
Gb!#[?&tF>'Rf.GgmBusP5tkn"C&=V-JcCPRVY@fjF\ul8f&=*%(_2_hg=mg&XtWF/q*r`;/t`gq_?,A"W]8-IeFG*3u>8N$If&7"?KM;i'+qX=8AuFm5Ia,2/U7.0HAaq[7qUliGI,N/U_$E+o_86W&Lq[<85nmedr<gb`ift<Bl5hNG@E-(f1kKK=ekgLc_@WqH'M%)n;H.!7bjrgAM"@o`lY=<(Ah<*u$L2[gud.Jc"a]pq2/#>(@]AH2cVmR+'/5cY$cWN6^SZm2B<AFVDoVa0EcC)=]Ob'/,hs-f*&%8Iq=C&!ZNqC4_Lg&i*gG"-Q;1rlHJ0i>2'oR@<UKG2]EY25@TMNtM,kW]H))s4"Ie_.4]eUd&^HgWk)#dV!f:/#V/l)[4c+M4618/9K%6<k"Fh@FJd9@9U(i\aM[T@E`%#Ot=_3cVhm'3@-Okk%2I2^CWCA,id9`e]di@M(qN(M<'OrH@'8QIK9b/V\tm/%o#ncZ$!_=W:M2B=9*F?7B)Ig`dCA?;%Tu(o#X!@[@#F@\7!7fSt$ko-jbek"t@2AO(s.h?6"0l;en!e0ltJMQ;JdfA!iu2qQfrWL$Gb*r'/O\hNlnce?BUi715,[l2IZDlp[("\X&\<4I%1#5u],67/OSSCY;E'FkS=8Hcl;tX.&Z5?=0fen-+tumT/68eMH0@#Ud;$k%3n92]:UZo6L8F7X,l3p^7%b52lag+-(qO1&~>endstream
endobj
32 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1335
>>
stream
Gau0CgN):C&:N^l3dt5:#suMa*E">ij4%+Hm5eB"0:![aWPN)?OYS_u9i:h8H?A+Hgq4s;`<auY5,Y<jkMUqZ0/re#,Co)'e8JW3)_`7agU*G(quV?V/,rZ*_Qr"%gV$)&KhgC1h-R]`cd?UaFm+_kgT-iDaJZWY6]NAud/^YHL$4s*ep#@O\?mp*CG\*1a&*HW'O'&eM)F/01:"<6"jd#ZEr$Y;Pm1R&$H"5.IP_oAU=V#fNHLa1@,.>>j0fANN4*LUmAC$:%G*+T&2L+kJg6]S.7sb9@hbW@i>SWlBaTnU63]+gS2n'MM:#TKL7VCq?Nmmr-'j)d`l&!kN!YA(+TY(MVo%%*9>8t%No5aY!>f^-(fFfjW;K/BcR=6'Ss;do=l6o1YNoHe@!hkLc\gP1Q\sU74.U7&[TD0g!O](U2nLZR997Ih%j]$ba"6^L^74LjQ>ecYpa($CjnhEF&H$@r5@gPuX,K9@9op:U5Sd<_)IWYV)+SWhOnnk5C2(C;/T\Z`rOj9C;*A<UmBlnZBHE'hCHY<eXdS>66DGMV+/,de3uKCQjsuL<'pM@]\Q/UFs8Bi=m)>i?I*J;e3+cm'M]s97AL,Tj6fALjrCm8uF[$#$*mejJ`[p%Wnd?kq?h3Lf(bAVN=^r3soVtt_r0YD,R2:Ju39"GOT1:5[&<.'<^sl'QeFP]6cTrX@)N@Q+X[2s5Du9?I/h;+:V.Ft/cn8EMomKf^@!Z6<!*1[V@QW6d*ttEdhkC!/_C!Is)n@NVSuZA5^Gra$):trF:1l%RVc(=6q6u#\T.0Gu76%g(po8*CM(!+Ua13Tji("E)_o*7\OS1DpAi4'[+.6.A\=Te6\+V3-&H@??B:Xd^#T`EtFk/%9_,?cQ)Xeh301LU8Z%UDnU28F#ku<`l&/_6IdtF1LCf&'XH#R6_S\E$o["(@]bfr/Zij"pp,teU5<R2^Mi/3L\$jQ<4KUt?D=q/-o`[Mp3UIf;:VJ)tOZ=\?,j;Q>bGB6>j%?PQZ!XqWE4JV80-p!C[s+W.)glJE<\=V5SmqV\4qSP3o4i9aT6R;,RG@:-E-^S]gPK(Y*J/e)BpO63n3mP9YIP[=u/4o+5SYPk)*^%pc2F/SZO!A[,XWKgXbRp+L4'2C3GEc(WX+(hOett5-:eWT30_doR1#;YN.BiTg0m7jI@^gK/II0)?IJUP@]MVugQ0nd_;)Hn2cbX>T\4jliG/p5`SXNa#qUQ(>AJd^-<u:4k:RGk5D0<OgJ9+`#eA2@]*>Qm!o4ngBP:Xl;EI$@F'$(Yd\C!BZi$:(CQ8Hlq;4]1OrHDLC)](oD'T.1CX0$,fb($1\poO~>endstream
endobj
33 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 630
>>
stream
GatU0d;GF-'Rf-p:A[F/@5%fkh6KY@QDmb>XXi*=02?IQ<j4$?,up4[T:N>dP"&ZR#fO9>n%Io:k*X$7%paZ4'ei>?N[UieF:-_LIAF@IP$3n^IE@Fq&g`"$""tcRM%X*lVb*Ds?BF(VIseXpLkS9\aLdE.35fE@#ro28qf,/9>m?bmBK1__et)61-./he)T>5t:hk*_UB%P28uSYQco9V$JFin$H:WO&@3S.@:s6/_!,TL6$8\j!lgaK/-I;%I2(cQT.^S;`f#r@]en(`+O_4261Af9PbBeEiAfbLMK90gn4/&WsRi`oXrl3Z2eMTZL^Q7mE#4hS.9M3mEhcRi&k6kqVkrkutdTJP0Nb[g_:.`r1FM94!oY1#haU5W&V>*qKrj'IA$K[4XWThF#na+0"3<Jd(nQ*o2=IgSi/a2H"s!\[)aejZkNLk<tdJ#D"_>Q$E=(V4.s&$9"6Z%!48(tb&CG3@UE>WU<A)cMTTsmbC0)+AH^C3E&+Rs.Ki[;`[`l1"te[GbmN(r,j^UEELIA,H5:A+-^@E'E,CJZEZ?b(&'-`ekpSd@O*,;;l/;6l^MCYUFH<ErqJRg4(qcNTq'i4c8FR'lj7I<Noi@OtZGT,fI#efVZo/sQ~>endstream
endobj
34 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1425
>>
stream
Gau0CD,91]&H88.0pb\p"A@<h*%+`:!QPq$*%BgGC7D6W,_NF[A,Fhm\-hc`46sAgn<S\W6#dUbmQCBj4HCj0g@XD#qfi-\kemBi%bq-c)S![)nB^%FDgZ9g1=ERtgTu2G\t(J64h!rIkVfbPX6XkXfj<G$=ho?lq#_?gBMZ@*`a;OL$`lIEGs?r4#K.1D54"=F$B:.'5XkfEEH[8f%eqjLh]!CKoQgoQ[o]6(jl8LfOEXBer++TYA\:b-r4uA:coTK\MAjo26kMm%KF*4q"(G6G\eRO`&7L<T@l).Sp2*52#r3cG(oB"5+q6k,$Sa;1YscrJn,_L&ic$(DK\oP*A%#8eKSHHo'iTFti"nD+F?EQDG"qk]$A(USY-LHS7#Gr0IW^&&6Pp&K/D/-f\NMnOAE\>%TX,'"dQU7R3n782>41P/j5m,NdNS^IE>Vk[(G=%:$orA+0Ba6k@LT]EYKL#;]Wo2#k,cEfC)DZpI#b/tP06us-\F]O4Du"F%\/>s3f8W[^e\ol5pE!3A$oHNTIoAlW\/09FoUP*4'm-=!++!-$9#)S5;u[LDB#\?[_&+5Ro_(9"FHa9GJ"FWBGkd$$OYk^I@b\S8oEfsnq'LR]U,SPgT,Y(XQ`G!X.oF]1Zg&K\i`1GO5\^,g$-m+co_TOp_K$/6jl7LWF8#OMFGeOWkis0U5srM1<K*a56);7dIN4Q:]1qd3]TD#"N-O+)%Lk>W:/j\O$em?/`Z&a_3W9qiKdib&b,C/iS(>L@2B]kH!T#J=a;Gi#C&<HB'HiO!1AG)ZO)A,2D52*NYLQW(Ld^r9Mgjq!Ekl=bCY-3+Oedk4N=Ymmqj4KJZp]cQOK-)N'uP;A,81?Go;n'o3R!j.8X$=0$K&tKP45(>lg*cm35a_gp5c99B"_#P6uNhDcHN25&^_(7HYUU'&RbV&-X1(TM]8d8UK=EA*SOQGN=`eo^hQX5c%"bp[BD`><tE:Q5hJX'cpRbfX6SQ_cF)tK[nm;iX.[U>BcqZ;PUoh1dB/$)6OSrBYs^(Mc1%(9T,MNO\l[a$/)Nqil$@W_uT$Lb"*lOFI)M1N<SblKN^6]1bpJ*nmLi!R\"stGtSG/'NJ+3Fu.pQ&,k*YYjZUKs2[dH!kCsL^1uY>5hdD$1j;OP)Ugl-`;T,)pGmV9T>.k@1995[NKnMH;(ntq)=C=rQ%Gel9&fstc![C).s7]8!:`)lpPKE!6IHalWpFS'(HT?ob2h?:#Nij"5L(X!27N'Cm^3r,SfYMR;r@UMQ>%/$.?^KsXS6F^7AeP;>G,i:TR#SAoi[+HK2Ln_<3,$m:!X53`JGl-jE923A4hP5!n8E_4BT9P6_D`ZlW>aEOM3N^*QO(k->?bP11t>kU\7Cteml-[)42,-H2YR7_1R,ISto,-pG0:Nb<"0,QAYr(rWA1fG7X~>endstream
endobj
35 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1337
>>
stream
Gau0C=``:f&:WeDFS([Q'F9@H"qn@fPLuj6AaS.>AmD;9[:$YY1,Au0'`WSc#=<qAJRbi#8^l;C-O*Q7D+)-+#N/Mk.b=kA2<\1NeFblp^;EsSn>fqB-Q=qVdAjS_\8:D!X3nR&3dRkd>KuGY$T?W6Y6Fk+V?OZ`W*VCJYdoWg_1cncr7%2PHBZG.dV+.rq"2:>8"<-s,LqrF'>'h<7Q&\sEd\Fai=-0:UIseg>H8T,nQd7LL,MP']fUl''0u#7oIY+(pOn,Yd#"o7$=Nt$n/TdXZD#]1UrV)IhKsf?Oe-]8VCF3fn.AUSF.]:lJ^4NoXp"Z.Z2(&u]UbaQk\q<bR:rk@<aZ+!0OtWb8M>c^4PTkO7bBBfcX=JM#17V)$p@ZAGk`#H$u&?W;;EN7O3gI8mM@a_J+hh$)p]&ZAAmRfhQJ_\d'OF!g>cUB[`;)0NZqN]j8D"hMqJ^Ro0FN^&TP>gG=UC5@Q/I2/e%j;nAKC$bVWf8Lc4fi-[tpD/pZd+$:.!QfC]j3%J4hd%t'RWbc$V!/pC$[[D<<B!>98`Ad?rmW<>4h(Pdrh]-H]'*F50^7ZrKD.j&srAUR_/5=BgQhMjA;8Y603`G87C/91_Dd.&Gci7B)7!@r%"P6;cZ7X(ZJn1fCAJJp6WVukqL?unMhojt+Y`U,W&MEabLZY"3%e*0,.FoO"bL_iBAB!,iX2]+MZ&`cXbG)*UQT#1@g/EHZ8-_.4D21Rn.kG\7Z6_7ZE.c&uplB\3._UgFj&aZQ@>D,kUgT5;u#qHbSUbCrfI_!^.kEAUk]#1f2:DSmLeP-^N]Bj:iDRrpD4g;U3+0mhNq;msDQk)Y*^:=lU/c*us-jW*H2c9as#&#))1qa9:Pg+b/.VhPE9+WtHp``%oRW`S-p15,G.AJ:t2LR`Y"NZe3'm]Cb^PE>M3faj<([&#m"(:X[OsJa@N06Gm'\G;bOUoKe6EL]ha#Nu-4=fG<QQu0o+H-bT@Pn!mbGFr7WKp0'*L&=L]3YNRQS$mBP"\Z%DUL[S`s:dA3[S\G*/mfpkN7Wj?Up(\C`Hk=QUhDW8cfZXrB?A<^SJ3ZQiM'o7"HiBPk:ZX5Ijnu73aoh7%Q`V?\QIU17lh\7!m)G1`^9O3\lM3qk`.E#$]mojI!keN[QKIVQf_cGoYAk%aFSAB7MslF8,QBF>EZFrpMQjDjZ.tD-FBbU>W7YH!5AbE+WYs-kH5r6]27k%dqXM)]Mp_@3ChN1E.mk<TSdEPISHPjK(!n*.o\,p_WE'8ls$PVFF'2RR^p%hSrW8F1WiUErHiI!mPb\=q.1,Y<eSTYuis1cQ46`Y'Pd`H:-Y@$q=4`~>endstream
endobj
36 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1211
>>
stream
Gb"/(;01/N&:WeDXGl192'GO?Kdo,^C\>LUWu8q_*k[R\>e/Xdab@/Yrc^"%["Kp;@h*_p(qq8^h!OOsI_3.s_,=W%ruZsqa"B2ED6P%"7prgM(:YIEX]rE9g%.;[NnNh]?$/rDCYITf=$<IMbtb`Xm<;tR5JO7e#B3g%]5?l<dt1SYK,OuiPPn[U"1+aDK6F:)0uEJ0g6q5/M.GL7fle@cSK!/tAWeoHpYdg<0ET_3PVi(SMus(S.5YECh",m/@..`WO?N<Q7pd#c&oe2/In@>8b2-r.\BhB=]C#Fqh3MKj8<S?G+nk1m7##A[)m+G6o]k=\T<$o!Bk:TLFoXuoA?_kfa2Dou'!J*nKN/OdL6:EB#goPa#bbn`-0mG&`e4I@=dut+HL4"DPY.%hOYT@;KXtJ'9F4@s2nMU8O]:fWgi=D@r^I&WTEZAmE3KR19t":3$-KTb[Rpg(OuP^@k&sjeGV*DY\bW'V8f<9&E53-lO"nQsjZ`O0-Tkjq.`R(>&UX1(;T7KQ_DH=VdkiqC*TKR\A+ZHtft8s^o/Af)TDnfk/+i"hl)u1#MFlLD3r*\@U+@W)1F1A@0k_9!c[i*h\6@l!(c:lRj`]otK%I\=/q@PCp`iLl(g]Kn17G^/72qD%4,IYlb`c)d+WHu?1@.=g>6em''8c[daE>$85Mm4/b-9her.*]]lmtZqMUaUg.]e9a11Kr?cP>rZTZUp@cgP).57L'$rS])[1$!m*_^f]a8^[/uHfA36Et\4F.0Z?MG]C#X-RsaX;auP+N(eGW937Z8'[nhDDO%TOYXDoF+fV3P33]Ji&[)UQA]XZ17a=BEK'6r2Q-MGc[e89i(@es>]4cEU2/dK"WLuP6Xc_lX<>+3XDk[SFAJ@p?Bh!HUPYr&]<qsUlEa67%Dh][35uHZ5JQ%+#E_X8IFc^BF+"=aLP-8\'meT+ALr[m2c'TV;j[&"BIWnr?$T@)*\J&>1WPj05E*h2_*O?$IKo1Ys<F!c*Obh)?b%k"7k_e&ILVR](+6*m#YA(ice3=6sWJ'c&9T[jVE1k@jFjX'p=7i/'m[l9?HS99+$Jj7[>ISdADlhdNd;oe`GP(V#&$04[/8rY`NdB/o6YN("niaN\^3B>Q)XgNiJ.09]TCfs0@\V_3@`=ukJP`a3S#Y,=$!\)LkO]`\Te95,<DeS-KG0"U':IZ2'OeokjeEP"T_8bJc]hr~>endstream
endobj
37 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1621
>>
stream
GauHKgMYb8&:O:S9`3tI0[9L6"e%?0S>9/+YuIA]*!@d3/5[V%oPuD$q>/Ah.>`(6;b[:^Ybh$Zbac"\fqAQr4dQ(/blD(0iU"tobD,Nr=K^W"GR/rldI!(Hm.>/4O6jr>^^CQ$nfuR-Z!mNQi-JcjU$4s'(m1SB5g580VU]]CcH(\K[W\AD%cQJ+@LCsPN3SV75DSb1`\3S6:\=#FmC<"^o"B7"+)NqJ36NSC(-MMB#gQb/Z[C"^eDMtA3*iCQ.Jn,\Ie3_[h:aG$];=>0g?k!n!b2(f0NA*F?oJ;fQDRd$*K$\@$*RJA'?jm9YY5oJcOKs=q1`TFIeU[hen2he*gegp/_Fs$[)q3:<!W,(7,]`DY[B6i+q[HrGaapp,n`[I_'Z6O\3A"JP`R$q8Fk4<1G8+!T-(l#$D3j6+C1]g!L!%Z!\\(N6-G'LJRXMI<*UeEPl:BjaEqt*J#(2L5h?]FJ"[jH/4kC:PiPNeTH_XH3A67WC=N^Y-`8XBJ/M@A/el8jQOp"=2Pjk`c6o-=R(c-oECh<'A[7[D;!+>g4ZT@FWB_eM*JQV_DRdcf1ngpG@9EoVB(/`_E!Oaor?nN5;'creH,c-a+,\8L76-nd$XG/7Dd'sXi(`CV_-_:sd5b$YWpZ=mY@G@hPu:!c:a?9FMAr!Rka?=$F*?C,LAuV$N<QL4FIC?5QUsC,6l/:HD;"3)_RAq$lTQ[RLB\#3nnWqXgBE.Io7CeYVqGR8@;?AWZJK(ZJPGe@%mSZLT"Rp8f.ms:n!:*&m'UZ?mZ1I.pG1R0*:0NPA(]JXF(88^F#HEIl?4u*[8J4P3snr-S9u$@EWNLI(:<d<!F;Ec(i6X1-rOB;]34`M2QBr,$qK5h_oEQEcT1[+,`a,/EL#O48>JS\Q--:A;i>;S0;ja!\;s2@0/#(1B<"h/ftE,$]fYmY%.Y.7kU)'7O-*7Kgul4FHp@CQr:T)WYD2Ku^-Wu6pDXQ`\:P=s[DY6Z[\p7OWHh)_,g_NY+CVfR(>fe:+D*8gOdl$S*FB7GW`^XsHWVRVAZB*[S6JP'&S\@=Z@I/f7t[j^+2Z%B8?r;%_h&cGe-TL!kgL)dRc-Ht[CbfP:#k.?<uaZaais>A6dZo6km[qJGYJr-PlrLG+0*>3;.>D]H$s`3ge_"4UA@J`12;WO^)U8P<At$)m^6uCX\desPI'Qg\YL/db%d*eGYD6bW.B0.-69/4[<Ohlo\jP4TKrmpU,hm(hQSK[6k>)Vj)**435q#7fL[Hj:Z)T?7*ndhK:3_LHb;1m<JaeiOu2s8kR`err$Ka1[Rt.mV=DPr=Qa;f<`*W?D=72Pc<J6tAoHN'oJk0M@.u?b9MJqq+7)Jk%8K;[e+I@k0U`=,$^>beX=n5A3qZODdi2,L<K^4sL8pp*'t_(Wc#\V;NErB@UHhrg)GE>El)W`G\Xn()"-4qh6(CIucMJecfDf5<\/<*k\@h\-BDlT>F%]BT)8FYhilDBM2+k[%c`8upL'MplYp.q/H"rba8;k^#^teapg"P*4dU>\+,qY6_DFE?AHaVXbB]NibBXnnX\Y:BJbDh=tM7/5+)j.Z56S6oa?jB-)"l\fUE7PT%^oScTE,6;*cCa_28,iSS4]Z\~>endstream
endobj
38 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1634
>>
stream
Gatm;gN)%,&:O:SD#G""j3RpR&Xg,jini*Y'5O*Sc#d>*Q6Ck\9gVmE:B/!8?:7\W9M)3D&d;e>loE!:YU&/d7EY(%$Li3?QWF:qKuk>Hhsk.G&O&l`*`#=D),_i@BhVnSN#`Od1&Bk96UNp.")tooojS8'm+FVEk9l'W3aj?aL7gfT&GGuGN.,)j@`@qo1RK_$Ec*+N_J<@TcS'e$W7qbP]J`#Y`'o[h2Xd-Br.Yt1V=L:TFi3fEMV5[g1JB@l_G8l-GZ^\AR,udKA*g&s,N:s+Z"5c'SE67Y%N1`D`IQd@m")4kWkfYUP6EKs.)??T8B,[PZ(eV2oLJO6n-tR*@7G2iRQkLMkN^:rD!>+`DSNl>S"-`DV"cB+9?u_i9e96_qIT]aKb>hE&nhU@=s=L():C#.KpZPUi(bq"b%2dH*,`^s[$o_]JdI\oboZ1A?&(h[o.+p8B)[/+lbhU,B.t>hBq7Vb\<Is?ZV7ka>YWQ<8@fq:/X]p5n,LJ>pKV`4\\"],)5.clMW)E7bIK'u@n8*(#Gnct_.Qro$[C\,8h:UH_bq>]?=rPi(&Z$u]Ja+CY28k#Qm*%X$<WT[WjP+M'[pp9KNnhK[(tN6i(kHREQRf!V4N5W?5Q4$c=[?fA^)!lj+g#>SaWg-T'Nm3)"5\@J-9Y?a":HB//d8Ra_nK(C;n4:H*LMYUR(q@964Gh'M@XN\m.MGkFsXjcg?65\E+TlG[KDnY[YUQndiWQrGgnO@I3A\l[,bMroHJujV!m@&s_SL:9,8Y$tr>7Dg#4=aY/Yp8na$@@5n&N,>-X^4p<SLSLAH*G`;r,NgYBWR.b92W4U<oM8qIBA(\HG?6kO8Oi]RF#!)1.OhIm.L60MXV*3mQX/l?[E3%8*Y.mud!%r\Foub:/6<rXdXh1#sdY.r<fsGPCXHQm01P35gR9GUC(T`mKgjp*_GIUI6FCH>K2D-quh;<68PreUl=,*jBQ^GBn$!bs`n(d"cSW9R[6Q0^SCYZL6L>uU_E<e2aQHR#*jd!;:I]KZ,X2CR`';.>@A20a27",;;Pbe"Ld<PSDq`6iQWRI*4bFD56DB99%nr1KNq*itpBN7_rkL6bi7>8)MjH'0DWi`IX1q4lWT!#;Y9DD@^\rfcWEd@c&U#^X2IN!G\9>6I;g&p*m'uPIR<Zj&]dP,9n'%,Xj5&&<eT9r`!^]'B9-A,:Jk6P)WI':I49tb!hRu<!&%=R"]CrZIp2BmiL./<PPjbUh!qUg:+C>[@m/9:t0)4j*r=3%8>dJdOXo9g)%):s"sB<sbRf@HQOcf"cV\gta#OJuaBpL9aYBuBtN9)R&q%]TkG`E+q/A1K!]NfMiP93E08h7]ud5S["4)]%$%^Z-<0^oPWDeIm5JR2#GmnS1<UmI@>9L3G]'[)-1j.&`iBFIj6aJ/#-q^?-KT5AD!BrN7mu+K>sd*.,frj'NtCB845C2m`DDeYRl&4mB0F=e%HKCth_;]RTqF`!KhZDF)a[NNkhWfB&7OST&rUFutF!P8uosL$_X_(<lKOSLHX*:LSV(S\j?3$@C.f'Fr_n?;HV&Y,=gOL)i0N;3+/qOpHCS_Nof2A)R5)Z$ibI7.Yk8.5\foB1.0W>$=#$*]3J\apUuD"4e'?F8~>endstream
GauHJ9lo&I&A@C2m.fXR)OLY!&F?7R-?8?.;_,-4;eA(P[%\G#":IOkoC';A84f*q.nOAi8[^)9^3t8'`=N)sL&UhJ!r-U6(KVc5*$u%!@huuC*P@f!rY[FCGT%sF+rNcd#F7gH#>@=]+V@CY4:=FZ.?eHSYmd%bR0696Bc<jV&/Hog+g=oKWJlDM0G.2&pd\"s:8)0`#a+NOGPn83QSHmm,F[pWJWWCR*GU3F`@M:Y1kA4%kC;=C?,IaFa*)X0FU9.l_:cMU:Rn>%Gn$tI!DD7Aq$AC?@Ih8=fE$tqJ0e'_4pHFjX`!8jD1KVU05:Z"#NS%IGX,!!P0"u*8U\/jptP+5pcJ[C%t'RphHpo4g?"1(m'$sBG!%F\G`V)FHi>Hfdmk*r8Oajr_GGuV=GMEBQn9lLh:q"0IacrD.U$'#i8_5+Z9?\4>,L`BW;h%kin!G2j[!Ya7GV-I>Iq'6Ee-3BWnHt,)'hW@q1S$CIA]n[WlBJk3gR`nR8hj+N`\ZDbHh'M.]j)3=-H:UPqm;51YDR7Mnju.';:K[SKb^!=u@nZk7sroTZ+>kF?Q]r>:QWU..p9![oOH5,No?GO=^-^$VPNJ(9@70RQR>j5GZ@g>?,u4g0kSpehuZ;N^g":Y,igoqU`9gdoTWnE-o@?;=MgU$<S"#`).O5TS_8>I(O3(,F]e/HnF(n@d1ILWJTZ*nng5FIYdI/`(U7&D)?"j8&`!k75$*7^P:OEZcU.I$-V+MMI?I&kEPP$\?Yr4>TQ+dlh:J<h[;Mt$bGLOl[8%F`G0XWnQ<"HNjF`@9iGfl[lWEOhd8n,nYfFJ%cqN3Wb7X/QC="l&gc',m2LASZ%Z@c^jg(,T:I+TTm[cm,+fk?!j/Nh*%RkOh1iVNWe"h#83i>aKKHXgApQoC@b&\:7XD-Ld5t]f&#q1Ndob:Ml8(LZL_O/KhuV(8dC@>qHcJZR*BKiDD(94#e#KWI#O=CW-V/?nB=&7b&fM+%#&Z$(WMdDI/NX.\>c-)'Z,g]_i`ABTBR/$^e;\Z9&Uk0CVKG8LL+(MZI;GWeZ2PX'1iOEImK0q:I7p3Y,8Nnn,AKkHc[(_'lBB_rnDX*R9AiJ#GLa.Sl)KEkj5VQp!_,t;r9/B_1X<ioHGY2%88n!IkLZ=PmG2-1%]aG?R[LcB2q*1o[tKfdbFL8,593CmSU\7de5T:&>ct"DI1,*q2611XWI^5Te2:O2F7Nadb[C&b15FJ:~>endstream
endobj
xref
0 39
0 21
0000000000 65535 f
0000000061 00000 n
0000000143 00000 n
0000000250 00000 n
0000000362 00000 n
0000000567 00000 n
0000000672 00000 n
0000000787 00000 n
0000000992 00000 n
0000001197 00000 n
0000001307 00000 n
0000001513 00000 n
0000001719 00000 n
0000001925 00000 n
0000002131 00000 n
0000002337 00000 n
0000002543 00000 n
0000002749 00000 n
0000002955 00000 n
0000003161 00000 n
0000003245 00000 n
0000003451 00000 n
0000003657 00000 n
0000003727 00000 n
0000004008 00000 n
0000004161 00000 n
0000005204 00000 n
0000006525 00000 n
0000007362 00000 n
0000008854 00000 n
0000009230 00000 n
0000010642 00000 n
0000011462 00000 n
0000012889 00000 n
0000013610 00000 n
0000015127 00000 n
0000016556 00000 n
0000017859 00000 n
0000019572 00000 n
0000000122 00000 n
0000000229 00000 n
0000000341 00000 n
0000000446 00000 n
0000000651 00000 n
0000000856 00000 n
0000001061 00000 n
0000001266 00000 n
0000001343 00000 n
0000001549 00000 n
0000001755 00000 n
0000001825 00000 n
0000002114 00000 n
0000002206 00000 n
0000003427 00000 n
0000004788 00000 n
0000006664 00000 n
0000008481 00000 n
0000010464 00000 n
trailer
<<
/ID
[<ab4fa5324f02268490d94a51d4d35c59><ab4fa5324f02268490d94a51d4d35c59>]
[<60bcc86fa22a6ca874effbf9cb4ba218><60bcc86fa22a6ca874effbf9cb4ba218>]
% ReportLab generated PDF document -- digest (opensource)
/Info 23 0 R
/Root 22 0 R
/Size 39
/Info 13 0 R
/Root 12 0 R
/Size 21
>>
startxref
21298
11788
%%EOF

View File

@@ -0,0 +1,443 @@
# Les 8 — Lesstof
## Supabase CRUD + Mutations — QuickPoll voltooien
**Vak:** Technical Foundations
**Vorige les:** Les 7 — Supabase Setup
**Volgende les:** Les 9 — Supabase Auth
---
## Inhoud
1. [Waar staan we?](#1-waar-staan-we)
2. [INSERT — data toevoegen](#2-insert--data-toevoegen)
3. [De /create pagina](#3-de-create-pagina)
4. [Server actions met Supabase](#4-server-actions-met-supabase)
5. [UPDATE — bestaande rows wijzigen](#5-update--bestaande-rows-wijzigen)
6. [DELETE — rows verwijderen](#6-delete--rows-verwijderen)
7. [Voting in QuickPoll](#7-voting-in-quickpoll)
8. [TanStack Query — client-side data](#8-tanstack-query--client-side-data)
9. [Types generation](#9-types-generation)
10. [Error handling — productie-pattern](#10-error-handling--productie-pattern)
11. [QuickPoll — eindstaat](#11-quickpoll--eindstaat)
---
## 1. Waar staan we?
Vorige les (Les 7):
- Supabase project + `polls` tabel
- `lib/supabase.ts` met client
- Homepage leest polls vanuit DB (SELECT)
Vandaag: schrijf-operaties (INSERT, UPDATE, DELETE), de /create pagina, voting flow. Aan het eind = werkende QuickPoll, productie-klaar.
---
## 2. INSERT — data toevoegen
### Basis
```typescript
const { data, error } = await supabase
.from("polls")
.insert({ title: "Nieuwe poll" })
.select()
.single();
if (error) return { error: error.message };
console.log(data.id); // de nieuwe ID
```
`.select().single()` = krijg de ingevoegde row terug.
### Meerdere tegelijk
```typescript
await supabase.from("options").insert([
{ poll_id: 1, text: "Optie A" },
{ poll_id: 1, text: "Optie B" },
{ poll_id: 1, text: "Optie C" },
]);
```
### Met returning waarden
```typescript
const { data } = await supabase
.from("polls")
.insert({ title })
.select("id, title, created_at")
.single();
```
---
## 3. De /create pagina
### Route + form
```tsx
// app/create/page.tsx
import { createPoll } from "./actions";
export default function CreatePage() {
return (
<main className="max-w-md mx-auto p-8">
<h1 className="text-2xl font-bold mb-4">Nieuwe poll</h1>
<form action={createPoll} className="space-y-4">
<input
name="title"
required
placeholder="Welke vraag wil je stellen?"
className="w-full border p-2 rounded"
/>
<input
name="options"
required
placeholder="Opties (comma-separated)"
className="w-full border p-2 rounded"
/>
<button className="bg-blue-600 text-white px-4 py-2 rounded">
Aanmaken
</button>
</form>
</main>
);
}
```
### Server action
```tsx
// app/create/actions.ts
"use server";
import { supabase } from "@/lib/supabase";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
export async function createPoll(formData: FormData) {
const title = formData.get("title") as string;
const optionsRaw = formData.get("options") as string;
const options = optionsRaw.split(",").map(s => s.trim()).filter(Boolean);
// Validate
if (!title || options.length < 2) {
throw new Error("Vul een titel + minstens 2 opties in");
}
// Insert poll
const { data: poll, error: pollError } = await supabase
.from("polls")
.insert({ title })
.select()
.single();
if (pollError) throw new Error(pollError.message);
// Insert opties
const { error: optError } = await supabase
.from("options")
.insert(options.map(text => ({ poll_id: poll.id, text })));
if (optError) throw new Error(optError.message);
revalidatePath("/");
redirect(`/poll/${poll.id}`);
}
```
---
## 4. Server actions met Supabase
### Pattern
```typescript
"use server";
export async function someAction(formData: FormData) {
// 1. Parse + validate
// 2. Supabase call
// 3. Error handling
// 4. revalidatePath / redirect
}
```
### Tips
- **"use server" altijd bovenaan** — anders runt 't in browser
- **Validate eerst** — voorkomt slechte DB rows
- **Return errors als object** ipv throw — beter voor UX
- **revalidatePath na mutation** — UI ziet anders oude data
### Met return values
```typescript
"use server";
export async function createPoll(formData: FormData) {
// ...
return { ok: true, pollId: poll.id };
// of
return { ok: false, error: "Validation failed" };
}
```
Op de client:
```tsx
const result = await createPoll(formData);
if (!result.ok) toast.error(result.error);
```
---
## 5. UPDATE — bestaande rows wijzigen
```typescript
const { error } = await supabase
.from("polls")
.update({ title: "Bijgewerkt" })
.eq("id", 1);
```
### Conditional update
```typescript
await supabase
.from("options")
.update({ votes: 10 })
.eq("id", optionId)
.eq("poll_id", pollId); // extra safety check
```
### Increment
Voor `votes + 1`: gebruik een **stored procedure** (RPC):
```sql
-- In Supabase SQL editor
create function increment_vote(option_id_input bigint)
returns void as $$
update options set votes = votes + 1 where id = option_id_input;
$$ language sql;
```
```typescript
await supabase.rpc("increment_vote", { option_id_input: 5 });
```
---
## 6. DELETE — rows verwijderen
```typescript
const { error } = await supabase
.from("polls")
.delete()
.eq("id", 1);
```
Met `on delete cascade` (uit Les 7) verdwijnen options automatisch mee.
### Belangrijk
`.delete()` **zonder** `.eq(...)` verwijdert ALLES. Altijd een filter erbij:
```typescript
// ❌ NIET — leeg de hele tabel
await supabase.from("polls").delete();
// ✓ wel
await supabase.from("polls").delete().eq("id", 1);
```
---
## 7. Voting in QuickPoll
### Voting form
```tsx
// components/VoteForm.tsx
import { vote } from "./actions";
export function VoteForm({ pollId, options }) {
return (
<form action={vote} className="space-y-3">
<input type="hidden" name="pollId" value={pollId} />
{options.map(o => (
<label key={o.id} className="flex items-center gap-2">
<input type="radio" name="optionId" value={o.id} required />
<span>{o.text}</span>
<span className="ml-auto text-sm text-gray-500">{o.votes} stemmen</span>
</label>
))}
<button className="bg-blue-600 text-white px-4 py-2 rounded">Stem</button>
</form>
);
}
```
### Vote action
```typescript
"use server";
export async function vote(formData: FormData) {
const pollId = Number(formData.get("pollId"));
const optionId = Number(formData.get("optionId"));
await supabase.rpc("increment_vote", { option_id_input: optionId });
revalidatePath(`/poll/${pollId}`);
}
```
---
## 8. TanStack Query — client-side data
Voor interactieve UI's (live updates, optimistic state) is `useEffect` + `fetch` matig. **TanStack Query** is de standaard.
### Install
```bash
pnpm add @tanstack/react-query
```
### Setup
```tsx
// app/providers.tsx
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useState } from "react";
export function Providers({ children }) {
const [qc] = useState(() => new QueryClient());
return <QueryClientProvider client={qc}>{children}</QueryClientProvider>;
}
```
```tsx
// app/layout.tsx
import { Providers } from "./providers";
export default function RootLayout({ children }) {
return <html><body><Providers>{children}</Providers></body></html>;
}
```
### Gebruik
```tsx
"use client";
import { useQuery } from "@tanstack/react-query";
export function LivePollResults({ pollId }) {
const { data, isLoading } = useQuery({
queryKey: ["poll", pollId],
queryFn: () => fetch(`/api/polls/${pollId}`).then(r => r.json()),
refetchInterval: 2000, // poll elke 2 sec
});
if (isLoading) return <p>Loading...</p>;
return <PollChart options={data.options} />;
}
```
Voor mutations: `useMutation`. Voor cache-invalidation: `queryClient.invalidateQueries`.
---
## 9. Types generation
Supabase kan TypeScript types genereren vanuit je schema. Geen handmatig typen meer.
### Install CLI
```bash
pnpm add -D supabase
pnpm dlx supabase login
pnpm dlx supabase link --project-ref <project-id>
```
### Genereer
```bash
pnpm dlx supabase gen types typescript --linked > types/database.ts
```
### Gebruik
```typescript
import { createClient } from "@supabase/supabase-js";
import type { Database } from "@/types/database";
export const supabase = createClient<Database>(...);
// Nu krijg je autocomplete + type-safe queries
const { data } = await supabase.from("polls").select("title");
// data is typed: { title: string }[] | null
```
Herhaal na schema-wijzigingen. Of automatiseer via CI.
---
## 10. Error handling — productie-pattern
### Wrap Supabase calls
```typescript
async function safeSupabaseCall<T>(
fn: () => Promise<{ data: T | null; error: Error | null }>
): Promise<{ ok: true; data: T } | { ok: false; error: string }> {
try {
const { data, error } = await fn();
if (error) return { ok: false, error: error.message };
if (data === null) return { ok: false, error: "No data" };
return { ok: true, data };
} catch (e: any) {
return { ok: false, error: e.message };
}
}
```
### Gebruik
```typescript
const result = await safeSupabaseCall(() =>
supabase.from("polls").select("*").single()
);
if (!result.ok) return <Error message={result.error} />;
return <Poll poll={result.data} />;
```
---
## 11. QuickPoll — eindstaat
Wat draait er nu:
- **Homepage** — lijst polls (server-side fetch)
- **/create** — nieuwe poll form (server action)
- **/poll/[id]** — detail + voting (server action voor vote)
- **Database** — `polls` + `options` tabellen met RLS open policies
- **Types** — gegenereerd vanuit Supabase
### Wat ontbreekt nog
- **Auth** — iedereen kan polls maken/stemmen (komt in Les 9)
- **RLS per user** — users alleen hun eigen polls (komt in Les 10)
- **Realtime** — votes updaten live zonder refresh (later)
- **Polish** — chart-visualisaties, deel-links (later)
Maar: **QuickPoll werkt end-to-end op een echte database**. Grote stap.
---
## Bronnen
- **Supabase JS — insert:** https://supabase.com/docs/reference/javascript/insert
- **Supabase JS — update:** https://supabase.com/docs/reference/javascript/update
- **Supabase JS — delete:** https://supabase.com/docs/reference/javascript/delete
- **Supabase RPC:** https://supabase.com/docs/reference/javascript/rpc
- **TanStack Query:** https://tanstack.com/query/latest/docs/framework/react/overview
- **Type generation:** https://supabase.com/docs/guides/api/rest/generating-types
- **Next.js Server Actions:** https://nextjs.org/docs/app/getting-started/updating-data

View File

@@ -0,0 +1,257 @@
%PDF-1.4
%<25><><EFBFBD><EFBFBD> ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 10 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
4 0 obj
<<
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
>>
endobj
5 0 obj
<<
/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
7 0 obj
<<
/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
8 0 obj
<<
/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
9 0 obj
<<
/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
10 0 obj
<<
/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font
>>
endobj
11 0 obj
<<
/Contents 24 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
12 0 obj
<<
/Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
13 0 obj
<<
/Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
14 0 obj
<<
/Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
15 0 obj
<<
/Contents 28 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 18 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
16 0 obj
<<
/PageMode /UseNone /Pages 18 0 R /Type /Catalog
>>
endobj
17 0 obj
<<
/Author (NOVI Hogeschool Utrecht) /CreationDate (D:20260607080655+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260607080655+00'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title (Lesstof) /Trapped /False
>>
endobj
18 0 obj
<<
/Count 10 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R ] /Type /Pages
>>
endobj
19 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1904
>>
stream
GauHL;0/3d&:XAWfU7(XH4`FE,j<Is:"lDpbk-3umIhUHpHYqqP7V[5a4'qY[h9gf*>@FY)J>Q_X`jGCm=&5)_8[#9hpFU&RgGV!UHf\jY(=0M$^2*?0c<-5/B4)s4g5p`FohkKi2@a=Dal1#gu8>B./:6TI,T\C;p4n;*uM-oJdTRF>e_1SYQVFhmt0Y"O8F<?]jl'%d'RS6S-PPLC]AeD?=<<W4*7h*7:dl5CJ[L$j'"A6KEm]f3;WF%[nCt<h8ge/B3>:Cb?RO.&uLTo34jibq'_GC+nK32gqr-;1=/n`EZZHDZ**_O/;c3pY*=;@DrNSVg/7>W,M6\fXEKL`e.R>q@,u[P46!d<IcLj>MQ%$k4p2Y-\XMd$RemS1T/f:ao0B9bfq(^ag3/EZNh?CiD3P6iPVHc>U/>Pa):caNLtugP>@Z(%7Q1tXY3"t6C(rIA1`t\R>1E;7K@h%gL8.\ca(QG&4*+5p,Q'0;-7mo\4hnt]Jm-;61F!7=GqdmqLtugP>@TmV>q,@rO&DUY^g)eC1r.7I$;,`H]K^h"2Rk4G9Is5r7ON>`SuH[r!s2c8D%SV(MtNkZ\'F"+`7KB%2'4fk=p$9_<7sd<j5hJt$4@/Y^O/2"?fB=B)4#9.(6tT>b;d*1PU-VuAkAD%YtUcA(:5;#[:$7]"\b&*gbo3E,?mr&EBu6pNIVm1CY%7upsfu[=8f;.#UYskUk2f$dA2$Z/\HGDk&f4U!-:cO@]41UY'YbZPf?Rf^q4ENcDo7Y1ko^Rmfh\;1,"s4o-f?nha"H!9XgPL0Dnsn,L`'66k2Me(B@GR6'\]%U!K%dI*:=.%C7Bs4V&&W+7"7uCKghk0`p*bj-MuLE2Au<LO2.1Jr0\mKODG[+f.Ze_`C?R/!LdW2P-J,FHX4p`=Y5#NDPNjC2cQ2pnkA<>n&9F@O$tE=Y:LdB\D1l9g'F7dd4s#P8ghC*]Lmp)\:bq)rfk,NBhF6ZPH_^E`BLpXNI0YFIk's4.S.V`NY\BD%<Eq4J6NRAUZgK9@V\[UMJIe:<1kBC?V;)__?k?%)Wc[o(RX38&%m+_D.e*a@]3gG?W&\_`nDn2?71+eB8D0IN2^BR8dmWeIb-9ai@(a*\4UV`+^CdOq9K@bZmAKILt/W&D2A+f]NlBUKiPMKSAi='j?C:,cO7)2;4,?4U=f,#YoS>S7@sOarJ9sik9\A)Y-a]>uG>:;@=$M+@Rm/&"XdE]JfsUgCsM::ZlASM^l3>Ub5dqk<)r`Y_mB!MsDY_aDs"6HVTM2;*q&jl4:gABT*H.`4e'OIduBk$&"%o>E7WR19Vn;1%>pV,+rq"Ap^3nL>KiKjSQ7;\#bP;)i2tOCKG`aH.3MKDWF)X/9%="l<u*c*rpFj7[o(q\.#,o6n7fseQt`P?;@_t@n_5<i!R(latPE3,XP!m698#5k'I2M(sWKn"Cb`\Rs\RNVhJ\4F5?44ciGTG-tu1u5otd8W'-q6fb<I9SnC(-OfT1\iHi*PGrAkNOfQs3/7kuX;k$<(9,^r"[cDaeEL9i:C")ba7=-30;35cY;`%fqoX$2h6HmpmJ9P=P(ulAF*oGXne%djC5MC6Y$eB[MkALNgqeP>$'YO/!"&jVZ'[u*u2cA,s;qcs'Ju6;2Vskqa1o3P*FOHlUCT#2'[_h/FfsnV:NAQta/<a9UQ1/R1d;tbgSB@^<l[i2m=#0#M(&R0&Df"g\mQ?1dM6B[Dp<P4t+fbOH3\L8Jr^<-#-2m`-?=JDfdN0>kd(9UF@ChCj3.HR70ZJS+mGoQ=+`n0>_))'iD_\]$&?.YuDdGdCc1C`(R]*\jGYIA%XDV]!:j')l:c3=CitIes?=H[&l>,<=a]91I+be-[`t[pWDrtWK9'1?o22*4!PKqQqQQZ<EOu83t#D_Nl5l~>endstream
endobj
20 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1254
>>
stream
Gb"/&hf%7-&:W5<EU]1@))Qi"Ub_;1=W8nWRr4e+Q['u9RoYcrQ7L)%J0=mhNfm)ZSms&P;!_W!@9PMV]2-JZO!b,GhlQgK/HIIN0YV)53(t+',`sd+#B)!+Q[j%o[1%Tl6UeqE7)HX18:hS0MPu>$$k1\)BF3*@@SC<_URft06XaEn.UYNKU=r-\L5!dKJ(Y4(3(MS`KM"[gp+8MhkX@nIm#YiN5qlQ[g7.Z365%F-*Pu=n_s7iJ?boN`@a!G!SnIOs<S5u!"]N](]Y8tVp8cI/[4T[3EXS(4c9V\7.YG4'oKMJ#>F&:'BL%$,PB7NAmf<9;&_nQYhU9i8'-UA3OagmB<IVd+*U*!fTH'`s,mLUa'<h.La9c*Ws8)HLUu=:oWu.klIa)_==*mW%;Gl.iWNaD8iHRm^H7H3q-rX'TLs*0lG8X#3F;RKm-"3$,$F@d69ak;#"IO([LH$Bl16>ZuRHNb=5T8nrG>g[g'qpfUmYoi%R0A&"Z&f6BadRA81^U#Mdt0@k22aR!5D)eEM_&7()q4VPm_J&3f.<RV1)XDCY-%ZjDK\6W_+damR<pm)0tn>5e^:;5Zj"q3UkhF/E<VIiN6'L12Orm0Z@_s791E<I+tqjTIXq2G:+I_OlhIZn[)WPb$]'?HTu<aGJ,j+WjNHe,Yg0SV*)+[R)lnccBail;VlS5]eT?$H<E`u-*!Y#oh:u.PE!(@K_[BatKj\,tdUmZWG^X`j,YDb1c-fUT=_II,BfdJo(7a!2O0@Q192=>Yp_;7g=GM3KL2'e,MA>PE4`T<eA;McL-PdbL]PkjX<p#er=e8<BDEg]R8,=n\_q`,/M;m'T5-5.qou6^f8<L5^AR)AmlB7.rp/<4jm"Dta_V/RLg=-m*bcf>]HCHm#\>Y]?r)r*):t]<AO=*R'jW0X?;lTNB(3>DS:5'%CV73)oh+MLeo%ALXZ#o&e;&XTmbDejXcmtCom39llcT&o7(LFBE%,HK^SZct5=F2p=Y=r0*ak'OMq2]RV($(G='`<B]0;$\g3Ns)B_VZ(XcNaT\n/>;>oQ1[)%<g,0[\jif_1(_UlO(S&qdO_*Z*E?YM>d"VW`j\c,)<ci`[Z=%"2^$EPj89aleC#l[i9R8)fTbJ5-#&N.%nI1T`<Y/-lRRF%FY'N_&1"iY]47;TAll;:Ub-]m08S`0=K1Mk3/SB50%;em=L\5qL[Wm%#gYpK6@,Lnq7(^a1Vt8(Y/<$I"S$*K10)t%m35K%uaXXRK~>endstream
endobj
21 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1219
>>
stream
Gau0BgMYb8&:N_C%.n'8i,\:u7-t]Q`Fse;8Ph9md0iCF/dZIT`DU+=h_QNhMGacp/Po:UajnZsZZB_kQ3"s_Fh_o'nB2f'3sLY]Hjra^$1iB1qqV)6&[&[,$AbocKH*N2g(0De0*A&-%XH.2;F@OJ+>"hhL))c&)8clI%b@gG#/k1iX9<"#dT6BU08Sa1W?kDFLR7^)s(q"-8G(:kFL1uk(sZO071H1^'$?G90MgZmrr&b(n4134<P6TJ"TGDo(N4(kE,OUY>PQH+\0N_4Gn'Ak0RqUcN'O5J\--Zo6/T5QWq1?Dnfc`RZ3\ASi$1_\)+!kh>EUa.Q!tSUO"e^CNStcCI@/dYGSj5n'on'2HIA0E[)6#*8P<:*e'JYU9rOk"4CXrG`830p,U5pUR`TeJ&>N(lB5f"o5ABUp(dY+L9B%[8X<%76:LNh5'moT69S+pMY=JK=C/0hp\+R<pC9Lt3i(cPijXVYNQk:RZ65"=Y2$as1WMT%T$3H$@,)Al.eLi8EN?`Rgph.PN!6f;V:q%3JQPOjL_^"db+7^\.-Wl^\$8W;_EP9Q%CA--"LceX)/((3?$aVD(:>1`Z*BMo>>=VCc_n*rN-MY"C!nX]e>$Su*"Kt+N-1=bKE,3uuRDIlt_FidN0Lm@<Rl&i1&1:=Th++HVSYa`MhtuXFdXrW!FUj+DB<N[JV'T(p24u/]QAnaWGGoq=878!$[D0p!`*`@]pA07$R_==T6[obcfbBRqUqMh6ep3ZM0@fIM8]R_`HW<J=o=q\\'DNPgPgf.hOCFOk9g)q+3&qL7qoS]Bn*7j9-L<0-P(rN/TQFP1?0PBC)`)8d_Er<P>U6iE/V_uE\$NhTo#8F4)+>Lsmh5E^TW2:\\ErAbf9jrRL%`s&;0_j7]"srDbY+bKI)1E$2qc?UVNA4PMWbpu0Hh$,*".[es&pTnZ*IJT)5UZ7]]f+d"9c1Z2#9G:`!i>o^8TJ,FMh+gM;p]m,JS7f<+81t(=uKV;+6jQs+<k9^oDf3s--(,IRMd/c9thoFe,->S)qXs-B7USV9kK`rH;7P2)t@DMJj^]-hoNA"_fR'=T4d<9;=-mHeDMhY*H85B7o'q$"@_2=r9=R83pIB-HlTN"2XfTmNuW5n5OPIK&7WFN`M)(M9ba@Dl5foSR[<b_`7o3MQB#Z?Ja#SAe_h`#k$EQ?Iuj%ep[4h.j$IeqPnp4r6YW846XV/[K~>endstream
endobj
22 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1654
>>
stream
Gau`SD/\/e&H8h>EAR=)Ba]fopq!TF>-u*Q'O/1qrFB;9(#%4]9:hq)*Ral[*VF$tafMp![NpYWML=i:p[I.(!QAEsr(ja$:DXS61LM1<.q!r7=M0=MMr:dhE5f5H5U&Q?bCS<es$4+)Efc/,b:Nf`2)/9b0T6iY%<.i82:GA_=?Qp,&?Vlh!f18_)0KS@6knft=qIZt4eCR,B=rSWW6RJHZi*6F*5T3T%B,C3PY!H8Z%`!,^V5*s58S*:-(CXMi:jg)aeje=k8Kr)J7n;mA];r[B<_.E((\'/&ZAM1Q_<sokY"uWFg5[I?H)4eO$S^)?=O+b"N>_sQmS7NM3/;SUWb1rcgYbgm)'KE4:.A,DdaRjXkV24I9@[$ob7(*6i7[mK'I?:l,P'ccmQ?=#&Boe5#%u8&@;]*VB*&<T^PIbMu?9a0VXOEIAV?F]!mq-FRMnX08$J,r*_J[AeJp3L.D6P9m:h'JSk0SM<Pj38sgoj1Tiu>:,&QHa]B<G]\A-3l/LENEDi]'?BMh15Nb0tAC6"ZWe$OC<XpT\?Fb+MrPUg8LrH6`G@HfR(`CkuVqYKSeo1`AjXu!(UT%I"Q,OMN5D<8:54#m/9hU=B@dFZ5F;HC3^)fO\pRr)gpaTRi4qs3Z+sL8bFc:V]BB]RhoMo.7%^D3Wfh=IH0bS1]'dmUM:nfi84uC:>lL-ideRdTJ'&("4.^EkN?PV\r=^9#)_0OX9T#&[),:I&"g,<[G$'M'<3it1CO.ce(CKE1PZ_i)(QuN:0?)IFD@[5_@U1>M[^l)Jc_;F8<],%trT4Po.6jn(.$,k^?,LnD>]o>O<::B\13QD.b!q(ath(Im61[JGE=maAnr$fdbMt?&`P];Zq,.Kb+7P:q\l-;`QODd5O9RmL<E#88r92TcnhmBBYpp"0Da]uPL$N:$Q3nZVn`'7HkJ9k-0f9!U[G[?[>Y']m91'?][cN'<J6eJ7Q:PYY)NBpW3Ra7kKK#5Pgm6/4T(sP&)Q?cpNV*n-1p-F(gUEnBo6gC;`B>tL>8'D!&DW%8B.=V+<E.7WM9+qWed>oHbNmi;NV$S)E&S[4A6;+s8?pHlNkOZW6-(:$<5<Wja\")>tS+1Y76?51]oZ2[-ALMqtfb6.FD3([p9\afZo.qa,c1'N+;aQEl3Wp&jG_]\E8$^)p,$qlq'3I:l:$lY@0T+knjB[)=X?CF;U;W+Uf+Xr)"X8=3-a:7>Uqjk;QkOh33t7iZrIm!(/h?eChoJoZViFh6:DP&05LPIUas=ZF"O5P&YATPtQ?X+:^MKFbIeEF]ZiBa@\J09.@"g:Skb4S<SG.niGgp3p_GAN#<+TE1%hNReYaiH9I9aX-Dn>Gn^73(+T-!9@ZHf;41o%>$]lsJ.d4jM>9k35jQAaUGG`J,EjuU;I]?4@iGgd@<crG4mFZ$hBbK\Z=iX;Vnj9oa?+$Yg7&VDa2WC34:FH3oJK/9,Xb-4!o>c[o)-G]*Pf!%:VpE;nXLk_B!_t'`D1jC_Hpm](g1>E"e*kDTOHX$O?:#J9g5,4'$:nIOlc`5X/-Va3U$I9s%6,dF=muo'op^jSlWB_BD8W1C+5^u>aWOh"YBQ/Dg>%rU`S6ofO#_&)`+96<$UT6[?W6\P0)/K0lP$_e`0%+$JZu$u]#I!bF70~>endstream
endobj
23 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1697
>>
stream
Gb!#[>Ar7S'Roe[3:k=`Y$ae+81MLug8;gjFDG&>`?#ErMG-*(AC75eVeqOq5*D'Wfl?#K"gZ-;A5PD^mlNWWJB`kZs4IJ3jVSKb&0M"4B0[XT_>#Up*Y1FD:d>*u`IL:8_^#5HK_>r+Hr*.'&P[k1!65Lf(.#kFi]Q02(cfSA"!q@KCd7tTMA_HTE=u2Fn&U9?#(\KLTpX8=>JBWg>PAau)t/`Tp"(TJDic:oY;M7M-8CEe]R\Demlm>YT5lQalpAhrcEn5;Kn`/10R.R=a'pV-\J4</`g8B.Ae"Bs7[0AR.,._t<`G?MZWbIb3mYt`igtbr-A-NtU5U<<j2bcf4N?f/*J(6lFu9PQ"^61h1t3][e>27^L<049pa0Zs\uLc;KWtt&qbDkK`Ir3iD;A2oX6J-.T_YTJN/"B*5UFo`W$.sjc7c)70%Zgke']-$66+NY9?X;2'rY-3iE$J6$0Ooe<uZ;7oT;M^T.U_XX[a_t@p7sB<!s6a3k[WI[?TrK/i6O]Kqa+XQXF<Q+S#Ls?0&,i7n3JDk`mV`-m_Sne"QnhIOVS73QRP&cke%e3ZI6K$fuC1BE()YJg\dXG9oM2F]84e<*t/i$&b'DFY<,k^tB$Ac%U&'+BMJB7QS6ChtnuiC!_$f)#$&u,'>6@YP2ZVEgbl=1Og9<<*_g(`_,$I7W1I#6UYVSbTh^26;>5hf=F)Qh[dp8JV)OU-a4FUN7E9/?Rl<ma&]EKnf%p)35Vc3_V9:?JR9X6+,Rjr3)tDZ7PouhBU'7;=h0m3#CaXjl>DI[6&bElA)&NNSZU-.E8JQa4'rs&/t23@2RjU6NR<4/mN4dT.Uf@1[/XIK&sNMETO?ad@q4/.5lH0/qsL#UQ(nYC,0g9<-U'2[16AQNPSq\GAS0m-R1^:CZ7%&pR8f)SK>JjXe,5XS^s0bD@YS?Y&o.R,n.6-t%uWh&T-<6S6j((@OB4rFeOhrZV=E\YHK;4WT>Kue0F\e#(^.MC6-^O;#RjPr['@f0RH\(u$.mC]@+]RDS#]\\(LfG\lVDl8b&?_d%6>hufJCXX38[_Z17)hN[!,.sSKfY*;<jqTXGu3B@Eao7T=%OP&feq2XGnVPKJMOi)mSP%c@^;ZZI[oXf(p-:.Dq^Y-YD`Ma>-n![`_^P6Gjn,?Dk?j8\W<_,LD^F3HXmdXVJr.6WYkg8g=Staf'J]hehSj#9F`$"p>\_]3d8TK_C+<hi=\nFPJPleBj0eS=L_9(r'rYJP)h`4*9Ko>j%G\o=6:D@lb$Xe)AWW'2aLO@r`+/e5hL<@oBG!OldtYJR>[Lp,=&AIKar<E+eKn1#;<S25G0U:'nBNe^\E&Su7iu<7=;m,o;cmd.[BP3&u4_s$j&cS\6AF)pl,JKPB0oo?4\S(@"M]I_AN_T2J.JpgbAdVo.[_^4A-b%Qj`@F:rpHb@tkgR^@T+VYpW'0Lq@jT7?nmYpXi;pBb62@2QqS!'G((nfIQ@9)sJ%$/em(V[RdXSsTKso?Lk8^,bknE0j4%mJVRmAkNC([FCp3Z=C^WQuB=._g1Xhan0q9@N#'Hdo+M/L,*WN';)[)Th8raIt?rQA68YqAAIJmr1cqH.F%"d0OrLZ!YO-FHiM3Kloapp_eX>7$en%?WsS\.AGc"C"ESRc<r!I9;79s$M/lR0WPfL:8nMPD;W@,tEV/5^e`:+bdY#AcF/+:J~>endstream
endobj
24 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1370
>>
stream
Gb!ksD/\/e&H8h>E<u-OkuL9$&P9CoLD4m8!++8"?9];5'Ua-/b*"!s$*^-'I7M!*94A\@g&[,&836:445N,E]MS+f6`[ul$K1js:<t@c#1E`P5m0k/0V3Ub*at3\&HLeDk90p?Eq][Td`Wbp7#!7gTRB89&g0"W>)+"5l7#.:'F#>V4:4JJ?YKO/dm.[D07?S@@q]&-5g"%I^[Y)]pHg&Cn'K>UMdX&H2Oiu.\KF'F;ukA^N'@72q#Z#gQ_o^[o/q^kD.2F.$T#d:S6`o8o3g!oD2K!ohSJiL1GAeD;WAOgg'4+8ZF'G%#5JrbP:Qbq!4]rQ[Kr$RDFqJKPnY'\O&2I''#W1(lS,s?GSj5n!gJJEnq9n`BKKA^$10gn?IZr$&mtEK.+.FNf^!&tFA_db$E@Be=3aqK/\'rfU<\BdJl)D5l;=:_*k_2n0Yb(3H[bEWM@Z8]NIJX3r\jIf]o#>J;lBNbS3pEKeL.q:`#rJ3#oR:e!_!1,3N_lFqDDMgE4&h=2c4;Il>cr<T%Nt/Uph0b+He6\6,\J6/<Y%;`AYgo82?F29P1IMEbf9^I-nl(ao"3Aef+uU$*qFn:0tBE3Dl<Og-fB9VT;ASaHJVP,oe#AXNWB@Y$<GfJB`E.4KKPPTemOTCF-W/Y.pXtj/p/G6Mu&3j71ljNO;i#lhD=F-sLS`V1J2$ICkjAN"O%IIt7?b%69J,bpYKb(7!(7m!.u4NgGdaGjfi;^;Kf`S0$f8HAiIEAOC00XQ/!tBUb5V^V\m?=agGRI%?hp:Do`.FkNph?4\O@/U6fq)!h@bj*X'Sa,XO"FB0DA,>$h2GVYkNl\8U(O&uO^GYIPfaOY1Nf-d+$To1Q#q>?D5-n5<RA=7OR;q3="K.GY,l9+8UNcNrC8%_UVpL&GglNab8X".YWZ,e\!'R9^dZ)_^4nf,.^!*L$3$<b$ee$M6kf/e,e+.8VJ\44,,DcfE+B'rs\bct44!G*F=Cl*>Mc"u>=BuT7MV".e6$#@8o&k9WG6a#oaSEono4@j5%+ca])R[[nT$S[1cBS5inJHOEg`)Xbrb9A`FfB8ogbu^$%E5$mg1$!k"&\?j&Tlm4"??[o$FHn@+MGs]r]f5@%.$D1q#FK*!OP'*$@^hi_@>#O"CB]4Lft83cSljQt^</P]j9`c-pK0DE9ZC-:c;KQ%0GsOQP$1d,j):*m2u@gD\Kn=]IX5f+h[P"3Ves_u[dGR0\?IQ?Nu-hjI0QOf/?q%j(3p-C\hWI.UZ0SH][PC8<8KEO%GTooIIR%qoB5iF\8Q.99HDGtm2PpPBD"KPcV5ARgV3^E@7(Y%SD,;niWp']RjA"($/OKGa@u/U$fBJl)uGQ+=RF`EmiU(5NAp~>endstream
endobj
25 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1751
>>
stream
Gau`SD/\/e&H;*)EA.U@l"Z*OhP`%5[\4-GT]fS/m3_uf,LNqX]iCfU(kM_aNdA%%A5RjeD&h1Dc$Sm;h=2PL!Q>kUhnp/dNs/W%$lFc=$CF1#=M0AiMoh:li?%_6(PjZA*H3-PD>p25:GQlPiWVGP+K/(hmslW"&L%e%dE_KS&#Fm.ZO$`nHdiiA&A_UIGk^QAic1!]*TDBOE7_hc-Od\=GV)"Qg&*'3c=$%6H;rWBPe"L9M\KcArq^jGJ*(NHKpt2#i.EX^\C%PAgkXc?iMF+d8RA@d";ZL)igFd?!-LDT9CVjhd+>:tFM;KThTBu28alrbmkB>6K#_)!/es%<a2c7s#brs?0Kf;H'4qoL$-&0J(WQVK-][XSU$]m`M'JrR4:LoQpBYo?59(9kS8`Mi&h_06Cqk_ia"Vnj0pW8.[m`*PB@)\^eDVR=0]EHppmE2=keU=[Ta*=Z54i)aqnm.Y?c0ut;V.%V2<hP%C^B<PV*q[*0h>D3!m\:\pdT)NUs$%dbgRc^<2M23A$4?N?D^+l2\.:La.SYV1iR2k(]d5<[r@?#Y_Q5HV_BE_%!A(Qeb%J6Z'Z*@`>fhu7qVQ<E<FU5<&_5*eMaI65Y$2^]7hG)P0<&Lj@/GVp<+,Z*F[kdFX>VkJ3-GCb7']C&M'2XH@2Wu!]XI/"_^qbG&)]7LG4ijogYhDCg%Q/<:er$St:uC4.&7KJfYc&j/gmJd(9@12K9G1C^O;SgT5T+f.u$ZZeOV^&([*]/kFoIcG7P=)`!T!@QDWjm!Lo"bU:o<6`N[8O]O#`J(3oQ2CEKd'STP]DBRL[Xl^cBSLS&"M`Dl=$$?RG>j'2US[an>MXrGObut=&Bpb.Mb;LtQ1`E"%`gt]2gV=tE0fqlZX`!e1e>aT48&@H!]+-=/"%^>NUrckZFUeV$?DYp0\s0h;9Bjt$1aQ/hTu-#i.XR>"0-H9""@#YC<G-!`eFeZlbm(&gPNBpcE@]'UT'_GEm9XY;cB"9;[@U`6;W]$sbqd%OYU#mOR6+73k1K(mD&0*aHN"u;H>5;C,CF?tpbq:?f;FqfO<[dG]=_"lenTIcd]L)V1OVJ7Cdp-?@De92CJG4\5EEdP6="Z`Kb=?rS(G?$ApR_:>`RT'kh(&-nX.4D]V71D'&1Ft9em\EV.KS3i/@iaUn0k:@MH5"kS:KITa*8tnF`=eor(qc\!;P;Q.N#U;nf$Pct]#NG$0&d2RDM31K2=IV3WdmUAZu&C3OiMLlG]LiWs2dAt*,+npjEb8hXhJR$`:c_Ym5RB]-M"qqhn[[ep7EK3%R(>q`t8=@9JJjHZe\.>nb.``ZCnm$RX5$0Uq@*`X+"TAo'5XWT8,eG#`Nm^.pNTu+a1eEX0cS)s"CAYNl:e4K2ns0noY%O[4_H>>`-JU79J8$=F59ulRh:49%uon@$*#V9N[?H_g[Gdg]7XuY-i8W;&e=)k#9(G<`I')1X@e<+BEkAF$$jd\*en[37^YF>n:2/EP:s3%faKR!m/3BEOFLmJhNE;=R/8!P@>n(Y]iU2%u'BjBm^7)?ebgbEdP2,gi`)rMTOelSo;$?c55kA^^@gmboR3o&M[QV&:%8N3&]j2YT?B8';/eV0!O2:%@q(.hXuj9acb'Z%6cb9cR]R3^ff=l9qO$N%l%MTposK(g\=n>>'9g&iA#)[3JOg0krNk\R36qVH6If^;1/i0>ICi&Al/AI?F,("W'U94'T<oE+1NI7CrY%,U$HVmoY.0_lM@Se,l~>endstream
endobj
26 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1782
>>
stream
Gb!#\D/\/e&H;*)E<u9S.2%N6?:\[bZ)q6A@+j*IY@$Pr<Fs0N,"me=B+5:LpQ:\.=c"(FB[P*`m-o+84Pi5F$j!Hd`-b&_J7$=SS.ZqY`YUm&jMCU2IN&g##D`SKGs3@;@olJl_UU:fAqLfq!!Rr]!ZX#7R0Oc\Li^C`.QPKSK0mGoZN1*F!mJ.ZL_E#2_**&["dCLc*qFqKgm)gUj4ZYIK#Tn6B)PTL'F/>1A[T)j_Sg(NN#+2GlgM;qn9['WAMh`="TGA-)9j\!:s._Z1\au,a<\r?Yn,kf(dHIR2O&Lg='Gr4?g5*Pb::-&Q+RN<E>eo9;".(GYgj<3`iXddaRq\t7=Kam-6c:FZ+kFKFa+*?Sr!6#/mpF'(op#>C!"0N=:99t)ufnH&$nt;DgA(.V%Li]ofQ\_=dhUIn%6pr-SDBdX9Y&c<-=+05S2t'j"]tdiQbI\^n!9<>$,,Nq//.IT@%%10R9JOol3'k/dRZE)"Apt2@`D'5m\"M;]h.;pWRnC%YT,qj@+5*:M!CtWr07&]N]C7.Mi5k`V5[pKID[g>4):`Yac&u5%E3c`JZi/.TjNfV(?MV)[-J9MjKDjY_J&[>JT)k<LB(P(gT.U%&<+W>4_0f)5pqiSC>2Hjn"rkXJFB`2"&fR1SihS>1_rJ4<F_Zj2RbiA.2cqe#8/1'\Y^8PMlkCH(7P9RDO9U&$(I[].RPFV6s?S-rZ7YGLt5h33es@%+T\H:.C>fIlAUOaclZDS"hIb281m_$<\s='TTXC8:B2>X6XF^>.(tE+$3\O7m!f\^Y7mt(J+<.,^ebEmgg%_+J1DRfE;MSO,1-XJqWV4-L65ZBTTG+$PJbW4(Yq.oo283=#g^\,iNUKXEGi,Au0TLB=$K]*U7$F=7L-leK`85.DDdo#a`Y&&\cPrlJ-4:WE&_])OXZbA9@`(S)00cm2gV>d8>sqRa3]T?aDdUc>7X%)26QrakbkR=Fe5<\9"[j%$M;N+bhZ2a'oonoh96\lDbhEop#%'99L]q7"BV1WHoO.9^Tsqm3&?q]"Zuu9]'_(?/KNK\5S,D>Mm#1Hg3=5ii.p(:lYYd]R*B"+SM-Z=@*kA%#]lKZSumZm>C)sNI7-?a_P%Z68cG2=3Ir7@qr;.N3o-q"k0[_%j3LNZZ$h\1UY7:]4#:/$%iS`Q\iX&o(E@Gm:k2G%N5l8+$=!0YaS>9,A;GsKrh$EAGEtIo@VG_9BV(1XaL(UZB)#r9II_EZPMc1bgO(ln$(OK?u<B7`m@jlal4X@NdtSt%fd<JCL\KN.gZn^)*JmmQ/;2ZZ/X'e'!$Aqd%6,P5`;?3W1bAfNh(P614BFaFV[-4LFTj?>c1VJZI4S[Rai=HY6qg>:lBeS>B#jp4/9>T@U7fG2P4F__m`cL^ga8i2so<2(h4HiC>PZ,ej#Y%c(e=a&:kFR_ItP4j&DR^4>i)l[9Ro3)7#d0$t<Are%6Rg.2.O7gg&@;1O-'6Gjq`g$Wg`jOL`\8'=a`$0YYeC#rA!lU'nrX*pVP5E573UCZB4)?6@_ebq]eoL'h%d_UR4e',>Ln6.NLhorrBKVTZK$9*snK//KI](K-CY@6.[B5A*G.KnYc1,D&NU04nS@]$E3dX+GeLIeF&b<0aBNrs..nhaa1J9K1_8cOm&>A_X[I)CFd$V<IVi(Ue`r$LX/;cIOplh`WO7dsM2TF:*f<6J5o*'/7ag:QnRT(6WJLViM(l/ILM0$4[Ts7"-RbpK&A&_/cl<Vk[O*W,=7<Q0;;<5BW[mrpQX=(^C!@?+@7\~>endstream
endobj
27 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1737
>>
stream
Gb!#[gN)%,&:N_CD"T'O2?`LNP)A@8RnJs5N0?rck+V&B6U<JEMH!+pM<jHa])YEaFCN^:B&#oq6!OM)mq6&5']2T6`uBP9jtM)+JCuV`!HX)*o2kEtDLJaFc#)A2J2dRP65rJZW#$.`.g(hG*nhciJGLP\?#Tm8JfkK;`cJl?Hmf-!*a&o-c`&"r5Q^*<J:DRq+l'M'[7`X-_s?K$qZ:>889etlRTY%M%!Sr0.>-oqKJLmJ@(q3^l0CQ?_M`dnb4mO6;tsW6,!M3pY\bJ2IL/fh8!2q<;&mCL*9N<HJe"a&"*B+kIF)&i/7lPq5i+op,`<f3!5-8V2@/*@c12_u?APkB2\ohdKcJ!?egeln4;Pr#fH/1&fN><F=.qLWe8bYk%^mPpInlq8rN7DZp;E8Z3OT-+Se-Wb#rJRj#GVu_j#ONC(*e8>BG!+7W5=EDg8[a7_,sPVC$f_d`n$QS.n%(O6r'=8&F)l`,cGe?8OZ0:S(ZSu.M:EO]7FPi)9UbnH68CRefk3A\J8]K*>cgu_U25LA/A\]-^AeZN25<*A3#l4*nVfVfGCXSKBm<f'Ie?ck"VGJdafIRJ&]6\pVebqkc+K[;U9CiV1/4>f*Z"/EL_Q'.u#dNGcoInK/49DRu@M?U<:M=Qm+9ug4I^Qf0`W(K,?)WWhbg&2D6=\6!T4:MC3*^1'r;0(&8&'5;e-QBmq%mQ_VT.-]\HRj5tS=<_3O'eKHDf=r1YK@+)7*+`&24f*qdc@Ge`@;_`G8VC`@O[0:QAQ*P7s=jQ'e`itZGQk6P_(bil##^?4)Ft4Pfpl94W?/s$0:3UYS,j/r&(D,tE*p9#0.\qS:Fa/qhBI2TS:)&O5Dc^jeAZEkGOXnJT5_Td03eQWpPdI"p($NV][*@(,*%_Xk.8gaNPfQ7i@Pm:aQ[mEjXX:%BAiW;n)J0>Q/<XfYq`k+4Ij!LBkn)<gNb=ee9jjn`2c'l_3N^<0VNr$m3/aLFE"_-*':\4L;f_k]JtiViOhg:JNpnBY8L[%.+-Qu%]Hh]/+rfbWq*l7peI?E3c%]Hk%6Z)KiC?&dmE,`O;g;=WGl_PT[S0]roSD<=q/R:p6l^%g.7K@.g[0;Qf;rnbm<;"+L#8=gM'K*k@0:?4H<d$0JAT^2OOHCIF,r#IFXWdOC/[daNC6]io?^B[,G?\+D07uqKejPF*3`6uAQ2uJ0s#O9Q;!m$U6-dL:G@(7F!S0J>Fa@I$%6,S"FsK1KuJ:V!4*>`KC".PFBn@Z']sO^56df2G?Pf%-%u6=J0LM4e>JSfMh>^K5/3J:/9^$X;7&jC9"p22;AbB&e""5(J2W:Aia1Z2/1u]QoL:(`X%TUNPlVnc?"GKZpDJ_n1VoRQ=@6MQ$R'^_f(JX=nP_)OK9u%?N>(n)PHe,_fm5QGl1Ec6DKM=_2b/M#HK/#)lCk4'*nJg(mUHrNp;f*H5#]:c6BkcM\HD*]:"V*-\JEFO8$Y'ZdB's@a8OB/ZgjdEYiLGmY*k'A_>NbPRf-(]s%C$X2658ICsPq!i7+6T"\,5bffU*d2A4_qd8nj$;ff-&.f(P]\P$L\1V6-'a<;;OhPXM2YBQ'"'/F,K'`L6VBopbh*MRiALWW,M?aM)">`FKLm:KGm(>Y$uR%2slhUs$c5qbO7C=![@>R.m7$Rij:F)S_E1$4o6hgDb?"Q&R0pd,q$06JJ\QDKNa3S^j4XUK4KgWfM!,[jhDWmL7pS*d*)oRZZg2aE%;~>endstream
endobj
28 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1350
>>
stream
Gb!<O9lo&I&;KZQ'mioCMBqsKhjgQXdW&07W9p;D!?kMY/J;Fk88e:i]-&D&YtVQG3h"4b=>M5,fR4N[G9I/3rNc-H<WfuUKDUr8o3j`b(-3Ut0B%]Vg#k03O8U>_^^3ml)#<*K!rE)"3"lkB:-A);$rS`udNjK"APS\S;XeC,P->''_Xuq-""/r=,RqR]=VRe(cMYJ7I@lf8SLBLgO6<_E9<EOc-XM'gDK^M?N(1$O:`HH$k]eXN+rJocq"XHan)9fg:hMR5/,7(3b[q&+^7W3[H[(09XCQtK"cVnXr6d4%AMf?5-X^ZZ[F%Xsg;mu@jGFbMi4uuW$eL&Na0.JrS2Be'6;Oeup2q0<RfoohK"jmnH@?4CC<E-DCq8muBUs8&qJ2R;=pG_,,[\*lm:=#&Lp<1]f%N"6R<^LPpo?VZ^u1cbZ/Gkp$Ts(ukR^bUSMnj9WmWR=BN.W(6XAi=A2MtUntOa>Pjf\Hq"7eq#4H.2\`nrVPdn6D2L(T]<Gqj;cV,e,hVa%YGepT83])(#RJV?!s7(4/3>u4)n-YK0PbNCB5!>4S^;IW,I.);&enZ93iXIjE'A#D%@.c?Y5A^qKcHoWSj()XKm>e!MYc:MbN<X8QDh0`=fNhNi-0fn(NsP;Z*62D)gl8ds=C?[]'r&iZai0u2E4]d)W,I$(rQ)%l?d!EHDoo6$]!ri3p2^LD%Va,F2f:kfo8-_@)\B==KsIZZ;%u3t$ClVX?7a=el-,E[gUmi[F0R1t24pX_[DBGOkEE_eecn_I<*WjRlDeMn,W-=@d&YH$LPUARJ^YL6k[t8(=;E;C7<4k%o1iR1Die%tXF%>%WkX9WP>`&.e1<-_rfVjk%(1XbKmH3N.XJ#dA,*eHgD,ROmPuBBN%6\hQ?pA]&3$EDhbiXVC06a1Y4hq[e[[)a[tLX9=8%l^+#m?blXI5]AoPF3Zh]mRAF<<Wi1\5I7Ln[8aq*-aCjTrN]VcH)n=u^_K/UA^H8.WPi)B4f`fZ8=aT5h=D?g%9bf?3s[hfFebPZ-%Kg>1S!ZjbgetNBT3+GH@W11a9gna7^$:!@LPZs5GRIctd4#<b]kH:je':_bIDD!a4d\.th(E'f.I*$N.b/Ur^R6AT7FN!c4HJS\Z@FIg!2m_bmlsXr:(Vh%L3EGnsYj'B%pAJsJk2tt+D[)r)m'Kul0c.<RB61RhT_d*__f2=:\<b0J44^es:n%s?<:LmqV4&&E\k9PsmZbm-mn^PmZBlYH00.hEq[V:2`M1RR]=]SL#Z4c0&]N+5Y#He&3dnq2NH;#V[eo@JUAa@BpX9^2r_>OQ'ce7M1rR;=0PFB6K6aB+p4;U3HJ0i.q\r_g#Oq~>endstream
endobj
xref
0 29
0000000000 65535 f
0000000061 00000 n
0000000123 00000 n
0000000230 00000 n
0000000342 00000 n
0000000447 00000 n
0000000652 00000 n
0000000857 00000 n
0000001062 00000 n
0000001267 00000 n
0000001472 00000 n
0000001556 00000 n
0000001762 00000 n
0000001968 00000 n
0000002174 00000 n
0000002380 00000 n
0000002586 00000 n
0000002656 00000 n
0000002941 00000 n
0000003061 00000 n
0000005057 00000 n
0000006403 00000 n
0000007714 00000 n
0000009460 00000 n
0000011249 00000 n
0000012711 00000 n
0000014554 00000 n
0000016428 00000 n
0000018257 00000 n
trailer
<<
/ID
[<2a963c3a26f31af55617bdce2d2e6bf5><2a963c3a26f31af55617bdce2d2e6bf5>]
% ReportLab generated PDF document -- digest (opensource)
/Info 17 0 R
/Root 16 0 R
/Size 29
>>
startxref
19699
%%EOF

Binary file not shown.