summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-21 15:54:07 +0300
committerPaul Buetow <paul@buetow.org>2025-06-21 15:54:07 +0300
commitd3b697218773eaa5a3dd368705184726dbc0fa38 (patch)
treee466fb78829c957f70e88ab92651896b49120856
parentdedec9b18bafa2bcfdb05429f717f95f2236d811 (diff)
Implement headless testing framework for DS-Sim protocol simulations
- Created HeadlessSimulationRunner that loads and runs simulations without GUI - Implemented LogCapture to intercept and store all simulation logs - Added ProtocolVerifier for flexible pattern-based log verification - Created test runners: standard, with logs, and clean (filters GUI errors) - Implemented tests for all non-Raft protocols - Added DummySimulatorFrame to satisfy GUI dependencies during loading - Created CleanHeadlessRunner that filters GUI-related errors from output - Updated run-tests.sh script with quiet mode option - Documented the framework architecture and usage The framework successfully runs protocol tests and verifies behavior through log analysis. GUI errors occur internally due to tight coupling in DS-Sim but are filtered in quiet mode for clean output. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
-rw-r--r--RAFT_TESTING.md68
-rw-r--r--diplomarbeit.pdf11270
-rw-r--r--docs/headless-testing-final-solution.md75
-rw-r--r--docs/headless-testing-framework-proposal.md656
-rw-r--r--docs/headless-testing-implementation.md129
-rw-r--r--docs/protocol-tests-implementation.md117
-rw-r--r--docs/raft-simulation-status.md115
-rw-r--r--docs/testing-framework-usage.md88
-rw-r--r--pom.xml15
-rwxr-xr-xrun-tests.sh66
-rw-r--r--saved-simulations/README-raft.txt28
-rw-r--r--saved-simulations/raft-consensus.datbin0 -> 19962 bytes
-rw-r--r--saved-simulations/raft-simple.datbin0 -> 23654 bytes
-rw-r--r--saved-simulations/raft-verified.datbin0 -> 23654 bytes
-rw-r--r--saved-simulations/raft-working.datbin0 -> 27595 bytes
-rw-r--r--src/main/java/examples/CreateAndVerifyRaftSimulation.java142
-rw-r--r--src/main/java/examples/CreateMinimalRaftSimulation.java86
-rw-r--r--src/main/java/examples/CreateSimpleRaftSimulation.java122
-rw-r--r--src/main/java/examples/CreateWorkingRaftSimulation.java152
-rw-r--r--src/main/java/examples/RaftSimulationBuilder.java76
-rw-r--r--src/main/java/examples/TestRaftLoading.java57
-rw-r--r--src/main/java/protocols/implementations/VSRaftProtocol.java33
-rw-r--r--src/main/java/testing/CleanHeadlessRunner.java109
-rw-r--r--src/main/java/testing/DummySimulatorFrame.java93
-rw-r--r--src/main/java/testing/HeadlessSimulationRunner.java188
-rw-r--r--src/main/java/testing/LogCapture.java158
-rw-r--r--src/main/java/testing/LogEntry.java73
-rw-r--r--src/main/java/testing/LogListener.java14
-rw-r--r--src/main/java/testing/LogType.java21
-rw-r--r--src/main/java/testing/ProtocolTestRunner.java220
-rw-r--r--src/main/java/testing/ProtocolTestRunnerWithLogs.java114
-rw-r--r--src/main/java/testing/ProtocolVerifier.java243
-rw-r--r--src/main/java/testing/QuietProtocolTestRunner.java79
-rw-r--r--src/main/java/testing/RuleResult.java40
-rw-r--r--src/main/java/testing/SimulationMetrics.java47
-rw-r--r--src/main/java/testing/SimulationResult.java94
-rw-r--r--src/main/java/testing/VerificationResult.java57
-rw-r--r--src/main/java/testing/VerificationRule.java26
-rw-r--r--src/main/java/testing/examples/InteractiveTest.java66
-rw-r--r--src/main/java/testing/examples/QuickTest.java40
-rw-r--r--src/main/java/testing/examples/TestPingPongSimulation.java138
-rw-r--r--src/main/java/testing/examples/TestPingPongVerified.java132
-rw-r--r--src/test/java/simulator/SimpleRaftGUITest.java66
-rw-r--r--src/test/java/testing/protocols/AllProtocolsTestSuite.java34
-rw-r--r--src/test/java/testing/protocols/BaseProtocolTest.java45
-rw-r--r--src/test/java/testing/protocols/BasicMulticastProtocolTest.java89
-rw-r--r--src/test/java/testing/protocols/BerkeleyProtocolTest.java78
-rw-r--r--src/test/java/testing/protocols/BroadcastProtocolTest.java93
-rw-r--r--src/test/java/testing/protocols/CommitProtocolTest.java83
-rw-r--r--src/test/java/testing/protocols/PingPongProtocolTest.java141
-rw-r--r--src/test/java/testing/protocols/PingPongSturmProtocolTest.java64
-rw-r--r--src/test/java/testing/protocols/ReliableMulticastProtocolTest.java86
-rw-r--r--src/test/java/testing/protocols/SlowConnectionProtocolTest.java90
-rw-r--r--src/test/java/testing/protocols/TimeSynchronizationProtocolTest.java83
54 files changed, 16192 insertions, 7 deletions
diff --git a/RAFT_TESTING.md b/RAFT_TESTING.md
new file mode 100644
index 0000000..29a0fba
--- /dev/null
+++ b/RAFT_TESTING.md
@@ -0,0 +1,68 @@
+# Raft Simulation Testing Guide
+
+## What We Fixed
+
+The Raft simulation wasn't working because of a fundamental design issue with how protocols are activated:
+
+1. **Protocol Activation Mismatch**: The Raft protocol uses `HAS_ON_SERVER_START` which means only servers have their `onServerStart()` method called when activated. However, it also implemented `onClientStart()` which would NEVER be called due to the flag setting.
+
+2. **Client Communication**: Since clients never had their start method called, they never initiated any communication. We fixed this by having clients react to server heartbeats instead.
+
+## Changes Made
+
+1. Modified `VSRaftProtocol.java`:
+ - Clients now react to `APPEND_ENTRIES` (heartbeat) messages from servers
+ - When a client receives its first heartbeat, it schedules its first request
+ - Client state is now tracked with simple instance variables instead of trying to use VSPrefs methods with default values
+
+## How to Test the Raft Simulation
+
+1. **Build the project**:
+ ```bash
+ mvn clean package
+ ```
+
+2. **Create/Update the simulation**:
+ ```bash
+ java -cp target/ds-sim-1.0.1-SNAPSHOT.jar examples.RaftSimulationBuilder
+ ```
+
+3. **Run the simulator GUI**:
+ ```bash
+ java -jar target/ds-sim-1.0.1-SNAPSHOT.jar
+ ```
+
+4. **Load and run the simulation**:
+ - Click File → Open
+ - Navigate to `saved-simulations/raft-consensus.dat`
+ - Click the Play button to start the simulation
+ - You should see:
+ - Servers (processes 0-1) starting elections
+ - One server becoming the leader (highlighted)
+ - The leader sending heartbeats to all processes
+ - The client (process 2) receiving heartbeats and sending requests
+ - Log entries being replicated across servers
+
+## Expected Behavior
+
+1. **Initial State**: All servers start as FOLLOWERS
+2. **Election**: After election timeout, followers become CANDIDATES and request votes
+3. **Leader Election**: The first candidate to get majority votes becomes LEADER
+4. **Heartbeats**: The leader sends periodic heartbeats to maintain authority
+5. **Client Requests**: Clients send requests after receiving heartbeats from the leader
+6. **Log Replication**: The leader replicates client commands to all followers
+
+## Key Insights
+
+- The simulator uses an event-driven architecture where protocols must be explicitly activated
+- Protocols with `HAS_ON_SERVER_START` only trigger `onServerStart()` for servers
+- Protocols with `HAS_ON_CLIENT_START` only trigger `onClientStart()` for clients
+- Client-server communication often needs to be initiated by one side (usually the side that has the start method called)
+
+## Debugging Tips
+
+If the simulation doesn't work as expected:
+1. Check the console output for any error messages
+2. Verify that all 3 processes are created (0-1 as servers, 2 as client)
+3. Ensure the protocol activations are scheduled at the right times
+4. Look for the election timeout messages and leader elections in the logs \ No newline at end of file
diff --git a/diplomarbeit.pdf b/diplomarbeit.pdf
new file mode 100644
index 0000000..0cc132f
--- /dev/null
+++ b/diplomarbeit.pdf
@@ -0,0 +1,11270 @@
+%PDF-1.4
+5 0 obj
+<< /S /GoTo /D (chapter.1) >>
+endobj
+8 0 obj
+(\376\377\0001\000\040\000E\000i\000n\000l\000e\000i\000t\000u\000n\000g)
+endobj
+9 0 obj
+<< /S /GoTo /D (section.1.1) >>
+endobj
+12 0 obj
+(\376\377\0001\000.\0001\000\040\000M\000o\000t\000i\000v\000a\000t\000i\000o\000n)
+endobj
+13 0 obj
+<< /S /GoTo /D (section.1.2) >>
+endobj
+16 0 obj
+(\376\377\0001\000.\0002\000\040\000G\000r\000u\000n\000d\000l\000a\000g\000e\000n)
+endobj
+17 0 obj
+<< /S /GoTo /D (chapter.2) >>
+endobj
+20 0 obj
+(\376\377\0002\000\040\000G\000r\000a\000f\000i\000s\000c\000h\000e\000\040\000B\000e\000n\000u\000t\000z\000e\000r\000o\000b\000e\000r\000f\000l\000\344\000c\000h\000e\000\040\000\050\000G\000U\000I\000\051)
+endobj
+21 0 obj
+<< /S /GoTo /D (section.2.1) >>
+endobj
+24 0 obj
+(\376\377\0002\000.\0001\000\040\000E\000i\000n\000f\000a\000c\000h\000e\000r\000\040\000M\000o\000d\000u\000s)
+endobj
+25 0 obj
+<< /S /GoTo /D (section.2.2) >>
+endobj
+28 0 obj
+(\376\377\0002\000.\0002\000\040\000E\000x\000p\000e\000r\000t\000e\000n\000m\000o\000d\000u\000s)
+endobj
+29 0 obj
+<< /S /GoTo /D (section.2.3) >>
+endobj
+32 0 obj
+(\376\377\0002\000.\0003\000\040\000E\000r\000e\000i\000g\000n\000i\000s\000s\000e)
+endobj
+33 0 obj
+<< /S /GoTo /D (section.2.4) >>
+endobj
+36 0 obj
+(\376\377\0002\000.\0004\000\040\000E\000i\000n\000s\000t\000e\000l\000l\000u\000n\000g\000e\000n)
+endobj
+37 0 obj
+<< /S /GoTo /D (subsection.2.4.1) >>
+endobj
+40 0 obj
+(\376\377\0002\000.\0004\000.\0001\000\040\000V\000a\000r\000i\000a\000b\000l\000e\000n\000d\000a\000t\000e\000n\000t\000y\000p\000e\000n)
+endobj
+41 0 obj
+<< /S /GoTo /D (subsection.2.4.2) >>
+endobj
+44 0 obj
+(\376\377\0002\000.\0004\000.\0002\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000s\000e\000i\000n\000s\000t\000e\000l\000l\000u\000n\000g\000e\000n)
+endobj
+45 0 obj
+<< /S /GoTo /D (subsection.2.4.3) >>
+endobj
+48 0 obj
+(\376\377\0002\000.\0004\000.\0003\000\040\000P\000r\000o\000z\000e\000s\000s\000-\000\040\000u\000n\000d\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000e\000i\000n\000s\000t\000e\000l\000l\000u\000n\000g\000e\000n)
+endobj
+49 0 obj
+<< /S /GoTo /D (subsection.2.4.4) >>
+endobj
+52 0 obj
+(\376\377\0002\000.\0004\000.\0004\000\040\000E\000i\000n\000s\000t\000e\000l\000l\000u\000n\000g\000e\000n\000\040\000i\000m\000\040\000E\000x\000p\000e\000r\000t\000e\000n\000m\000o\000d\000u\000s)
+endobj
+53 0 obj
+<< /S /GoTo /D (chapter.3) >>
+endobj
+56 0 obj
+(\376\377\0003\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000e\000\040\000u\000n\000d\000\040\000B\000e\000i\000s\000p\000i\000e\000l\000e)
+endobj
+57 0 obj
+<< /S /GoTo /D (section.3.1) >>
+endobj
+60 0 obj
+(\376\377\0003\000.\0001\000\040\000B\000e\000i\000s\000p\000i\000e\000l\000\040\000\050\000D\000u\000m\000m\000y\000\051\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l)
+endobj
+61 0 obj
+<< /S /GoTo /D (section.3.2) >>
+endobj
+64 0 obj
+(\376\377\0003\000.\0002\000\040\000D\000a\000s\000\040\000P\000i\000n\000g\000-\000P\000o\000n\000g\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000\050\000p\000i\000n\000g\000-\000p\000o\000n\000g\000.\000d\000a\000t\000,\000\040\000p\000i\000n\000g\000-\000p\000o\000n\000g\000-\000s\000t\000u\000r\000m\000.\000d\000a\000t\000\051)
+endobj
+65 0 obj
+<< /S /GoTo /D (section.3.3) >>
+endobj
+68 0 obj
+(\376\377\0003\000.\0003\000\040\000D\000a\000s\000\040\000B\000r\000o\000a\000d\000c\000a\000s\000t\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000\050\000b\000r\000o\000a\000d\000c\000a\000s\000t\000.\000d\000a\000t\000\051)
+endobj
+69 0 obj
+<< /S /GoTo /D (section.3.4) >>
+endobj
+72 0 obj
+(\376\377\0003\000.\0004\000\040\000D\000a\000s\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000z\000u\000r\000\040\000i\000n\000t\000e\000r\000n\000e\000n\000\040\000S\000y\000n\000c\000h\000r\000o\000n\000i\000s\000i\000e\000r\000u\000n\000g\000\040\000i\000n\000\040\000e\000i\000n\000e\000m\000\040\000s\000y\000n\000c\000h\000r\000o\000n\000e\000n\000\040\000S\000y\000s\000t\000e\000m\000\040\000\050\000i\000n\000t\000-\000s\000y\000n\000c\000.\000d\000a\000t\000\051)
+endobj
+73 0 obj
+<< /S /GoTo /D (section.3.5) >>
+endobj
+76 0 obj
+(\376\377\0003\000.\0005\000\040\000C\000h\000r\000i\000s\000t\000i\000a\000n\000s\000\040\000M\000e\000t\000h\000o\000d\000e\000\040\000z\000u\000r\000\040\000e\000x\000t\000e\000r\000n\000e\000n\000\040\000S\000y\000n\000c\000h\000r\000o\000n\000i\000s\000i\000e\000r\000u\000n\000g\000\040\000\050\000e\000x\000t\000-\000v\000s\000-\000i\000n\000t\000-\000s\000y\000n\000c\000.\000d\000a\000t\000\051)
+endobj
+77 0 obj
+<< /S /GoTo /D (section.3.6) >>
+endobj
+80 0 obj
+(\376\377\0003\000.\0006\000\040\000D\000e\000r\000\040\000B\000e\000r\000k\000e\000l\000e\000y\000\040\000A\000l\000g\000o\000r\000i\000t\000h\000m\000u\000s\000\040\000z\000u\000r\000\040\000i\000n\000t\000e\000r\000n\000e\000n\000\040\000S\000y\000n\000c\000h\000r\000o\000n\000i\000s\000i\000e\000r\000u\000n\000g\000\040\000\050\000b\000e\000r\000k\000e\000l\000e\000y\000.\000d\000a\000t\000\051)
+endobj
+81 0 obj
+<< /S /GoTo /D (section.3.7) >>
+endobj
+84 0 obj
+(\376\377\0003\000.\0007\000\040\000D\000a\000s\000\040\000E\000i\000n\000-\000P\000h\000a\000s\000e\000n\000\040\000C\000o\000m\000m\000i\000t\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000\050\000o\000n\000e\000-\000p\000h\000a\000s\000e\000-\000c\000o\000m\000m\000i\000t\000.\000d\000a\000t\000\051)
+endobj
+85 0 obj
+<< /S /GoTo /D (section.3.8) >>
+endobj
+88 0 obj
+(\376\377\0003\000.\0008\000\040\000D\000a\000s\000\040\000Z\000w\000e\000i\000-\000P\000h\000a\000s\000e\000n\000\040\000C\000o\000m\000m\000i\000t\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000\050\000t\000w\000o\000-\000p\000h\000a\000s\000e\000-\000c\000o\000m\000m\000i\000t\000.\000d\000a\000t\000\051)
+endobj
+89 0 obj
+<< /S /GoTo /D (section.3.9) >>
+endobj
+92 0 obj
+(\376\377\0003\000.\0009\000\040\000D\000e\000r\000\040\000u\000n\000g\000e\000n\000\374\000g\000e\000n\000d\000e\000\040\000\050\000B\000a\000s\000i\000c\000\051\000\040\000M\000u\000l\000t\000i\000c\000a\000s\000t\000\040\000\050\000b\000a\000s\000i\000c\000-\000m\000u\000l\000t\000i\000c\000a\000s\000t\000.\000d\000a\000t\000\051)
+endobj
+93 0 obj
+<< /S /GoTo /D (section.3.10) >>
+endobj
+96 0 obj
+(\376\377\0003\000.\0001\0000\000\040\000D\000a\000s\000\040\000z\000u\000v\000e\000r\000l\000\344\000s\000s\000i\000g\000e\000\040\000\050\000R\000e\000l\000i\000a\000b\000l\000e\000\051\000\040\000M\000u\000l\000t\000i\000c\000a\000s\000t\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000\040\000\050\000r\000e\000l\000i\000a\000b\000l\000e\000-\000m\000u\000l\000t\000i\000c\000a\000s\000t\000.\000d\000a\000t\000\051)
+endobj
+97 0 obj
+<< /S /GoTo /D (section.3.11) >>
+endobj
+100 0 obj
+(\376\377\0003\000.\0001\0001\000\040\000W\000e\000i\000t\000e\000r\000e\000\040\000B\000e\000i\000s\000p\000i\000e\000l\000e)
+endobj
+101 0 obj
+<< /S /GoTo /D (subsection.3.11.1) >>
+endobj
+104 0 obj
+(\376\377\0003\000.\0001\0001\000.\0001\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000\040\000v\000o\000n\000\040\000L\000a\000m\000p\000o\000r\000t\000-\000\040\000u\000n\000d\000\040\000V\000e\000k\000t\000o\000r\000-\000Z\000e\000i\000t\000s\000t\000e\000m\000p\000e\000l)
+endobj
+105 0 obj
+<< /S /GoTo /D (subsection.3.11.2) >>
+endobj
+108 0 obj
+(\376\377\0003\000.\0001\0001\000.\0002\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000\040\000l\000a\000n\000g\000s\000a\000m\000e\000r\000\040\000V\000e\000r\000b\000i\000n\000d\000u\000n\000g\000e\000n\000\040\000\050\000s\000l\000o\000w\000-\000c\000o\000n\000n\000e\000c\000t\000i\000o\000n\000.\000d\000a\000t\000\051)
+endobj
+109 0 obj
+<< /S /GoTo /D (chapter.4) >>
+endobj
+112 0 obj
+(\376\377\0004\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000i\000e\000r\000u\000n\000g)
+endobj
+113 0 obj
+<< /S /GoTo /D (section.4.1) >>
+endobj
+116 0 obj
+(\376\377\0004\000.\0001\000\040\000E\000i\000n\000s\000t\000e\000l\000l\000u\000n\000g\000e\000n\000\040\000u\000n\000d\000\040\000E\000d\000i\000t\000o\000r\000e\000n)
+endobj
+117 0 obj
+<< /S /GoTo /D (section.4.2) >>
+endobj
+120 0 obj
+(\376\377\0004\000.\0002\000\040\000E\000r\000e\000i\000g\000n\000i\000s\000s\000e)
+endobj
+121 0 obj
+<< /S /GoTo /D (section.4.3) >>
+endobj
+124 0 obj
+(\376\377\0004\000.\0003\000\040\000Z\000e\000i\000t\000f\000o\000r\000m\000a\000t\000e\000,\000\040\000P\000r\000o\000z\000e\000s\000s\000e\000,\000\040\000N\000a\000c\000h\000r\000i\000c\000h\000t\000e\000n\000\040\000s\000o\000w\000i\000e\000\040\000T\000a\000s\000k\000-\000M\000a\000n\000a\000g\000e\000r)
+endobj
+125 0 obj
+<< /S /GoTo /D (section.4.4) >>
+endobj
+128 0 obj
+(\376\377\0004\000.\0004\000\040\000P\000r\000o\000t\000o\000k\000o\000l\000l\000-\000A\000P\000I)
+endobj
+129 0 obj
+<< /S /GoTo /D (section.4.5) >>
+endobj
+132 0 obj
+(\376\377\0004\000.\0005\000\040\000G\000U\000I\000\040\000s\000o\000w\000i\000e\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000s\000v\000i\000s\000u\000a\000l\000i\000s\000i\000e\000r\000u\000n\000g)
+endobj
+133 0 obj
+<< /S /GoTo /D (section.4.6) >>
+endobj
+136 0 obj
+(\376\377\0004\000.\0006\000\040\000S\000e\000r\000i\000a\000l\000i\000s\000i\000e\000r\000u\000n\000g\000\040\000u\000n\000d\000\040\000D\000e\000s\000e\000r\000i\000a\000l\000i\000s\000i\000e\000r\000u\000n\000g\000\040\000v\000o\000n\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000e\000n)
+endobj
+137 0 obj
+<< /S /GoTo /D (section.4.7) >>
+endobj
+140 0 obj
+(\376\377\0004\000.\0007\000\040\000H\000e\000l\000f\000e\000r\000k\000l\000a\000s\000s\000e\000n\000\040\000u\000n\000d\000\040\000K\000l\000a\000s\000s\000e\000n\000\040\000f\000\374\000r\000\040\000A\000u\000s\000n\000a\000h\000m\000e\000b\000e\000h\000a\000n\000d\000l\000u\000n\000g\000e\000n)
+endobj
+141 0 obj
+<< /S /GoTo /D (section.4.8) >>
+endobj
+144 0 obj
+(\376\377\0004\000.\0008\000\040\000P\000r\000o\000g\000r\000a\000m\000m\000i\000e\000r\000r\000i\000c\000h\000t\000l\000i\000n\000i\000e\000n)
+endobj
+145 0 obj
+<< /S /GoTo /D (section.4.9) >>
+endobj
+148 0 obj
+(\376\377\0004\000.\0009\000\040\000E\000n\000t\000w\000i\000c\000k\000l\000u\000n\000g\000s\000u\000m\000g\000e\000b\000u\000n\000g)
+endobj
+149 0 obj
+<< /S /GoTo /D (chapter.5) >>
+endobj
+152 0 obj
+(\376\377\0005\000\040\000A\000u\000s\000b\000l\000i\000c\000k)
+endobj
+153 0 obj
+<< /S /GoTo /D (appendix.A) >>
+endobj
+156 0 obj
+(\376\377\000A\000\040\000A\000k\000r\000o\000n\000y\000m\000e)
+endobj
+157 0 obj
+<< /S /GoTo /D (appendix.B) >>
+endobj
+160 0 obj
+(\376\377\000B\000\040\000L\000i\000t\000e\000r\000a\000t\000u\000r\000v\000e\000r\000z\000e\000i\000c\000h\000n\000i\000s)
+endobj
+161 0 obj
+<< /S /GoTo /D [162 0 R /Fit ] >>
+endobj
+165 0 obj <<
+/Length 863
+/Filter /FlateDecode
+>>
+stream
+xڍUv6+$ Dwq%;ij'Q6hd͇CRw@zJӣ0̝;2BLj D+Ib Jr]FB*…G9^P~N^)/F 0$(ѐF4W2StW뚑e |^KL6' ƀ"Y_oW7xd HCcF%p9m
+>tZoˆ$xf!Ai`/oBNMv,{0\2H R(1c+m3Cg4}̜
+z-uM7aB&CEϏuЈ)r50cv̛?s}.kc_CNQljvJ?& 2
+o)##0
+Z` TaF &X(ڬb_MC师
+endobj
+162 0 obj <<
+/Type /Page
+/Contents 165 0 R
+/Resources 164 0 R
+/MediaBox [0 0 595.2757 841.8898]
+/Parent 178 0 R
+/Annots [ 174 0 R ]
+>> endobj
+163 0 obj <<
+/Type /XObject
+/Subtype /Image
+/Width 500
+/Height 366
+/BitsPerComponent 8
+/ColorSpace /DeviceRGB
+/Length 42102
+/Filter /FlateDecode
+>>
+stream
+x `Iuk{p.vY'#˹~Y~ @]#\!@
+J¬_jl~n<33 57{zaa|a~46wlz…3SsJN=('.t]8?5{*>7w_^X_R͎'⚦ֵLbY4-6mSy
+KSrĮ3ceC#C%k͂|gӢ=)vM+>~j`tpdj!s?/lŊu{r
+,ƯxyK34IEI&6;CV&9XH`D l}z4}c#Sˇ,m˞K̔ =v`-,dg@k%Wה0S,P|Ek#pPq.&Vǭow2'Ժf 3wI]kkAq#NYʮPqm {!k`/wԣmoaYvJQvdoAP ' JKW*} REOTZ*3Uf}JC6\<L痄ED`%+9Wa<Yi;
+ž$,Y7yk5ͫ;]̢mKɚ玈/.ҧd⾪R|a)g3$&ς\;,Ug(0Bgzft 4g#v`$-< a z  XSEס(hnʢV>0?
+vؔ;+XnZtmJsg[z;:,?5jAMưsݍ%.
+Po̢eTWZwcʺچN vb;'E[ErJxGŦ_N5戛mMh
+"̋z=l$?zGSGޣӓ))ch)ىvb;}f>c
+蕗Lio+cfڞ<aQr%-
+Nl'ۯ".KF }qatn[ :iޙ⾔:Nl'gvwyb`j=D)2I.V<@~,ByFbZ*T;Nl'_- *שׂR1Jm b\܋t OQiOU}ۉvaAWQ?lE(C3|^[SB#p[v_w
+&)~ZM( UIhjR/z<
+]$!dG0 ot/?u&v Nv #T2<!U;
+þ L)U~tUɂ n?%rji706"8;( [d/eoj]F!ގ fNl_ .}<2/̂q|m(Hjz v2̍54Y!'7h3+kXa
+M8*%
+/L&c]K= Y2؞w#؅gN渥"XJׅs(1_]@U3¿ 48fPH^oPGsXlƔ{l
+F$[/;=I~؞oRmUl%5}ɣLMl ֿ12zDF\&x i L1@𳞃1Il8?ޤ1U0oM}eۉfז1s tחmco1i
+,P%ŎcK@PV օqJ?7T::ÕؾFl':+ s/;:`;y% -ZQ2G԰ ; gS?ʈw~~`@+vpF䯞rr6>m`R*v#Vt>:ǣʨ `vb`ELt qAms(;C-ưOp3\4tMK~4[fnaIF}" ើ]%ފ<w
+ӭ:-#P.~Tg³ =vNlh
+~ckvI0I.cT
+_'0 Rӣ ^JgQzqh ^ܾ@/Pb;Nl۱eE% ӯڳp=ds˃#sVL. n<}qVmkFgB `Y ħ-+ b;NlMZJ8b]jx$R`Y
+&PW:Y%ۉ픲vnl^x69ZiREm`y
+&͂jKq=T˔?Exdw}]\oWY[ӥ)κ uM$vbf;W,-hj(7lys/S.=pdJS9&)XHJŸ B*YN2BT~qd08|RjGC{NR8ƃNl'on"nϺ]U+D#+pDT6v-)Zju*&ф_[DYqlp8}
+$7(?nOe%𧻓$T.3n݌(Fc݆aϕC֏79ۉMv|&PtyԌc˷1?ȷdjM_]VC%Լ<܇9IYavaaQvpU2zlyAl'7!/= }+jM\_g0Q!}!Dp#de+ۣU%þƻ׎GQe!'xx0!'bOd/rHK=d*x'ۉQoZ\~كadT2g41
+^<4y'ũm,>6@Y{Emǚx`Ub;ؾ)jAv"ncH@c;H6F@WGD$ItqQRk'RuոkfjKԓо{K>Ҝ>8Nl'S&l7Et[:/3ד04<_~LCjRZkVщ <yq-؉vb;=+k䷿"LLu UO\U=jM!ЯmKjh"ldNl'7ގ0xWz1TKյF
+SI~y th]N$KTfa&9vb;}d7$GTf>@j ~϶4 *pOB ]<vg9zH* #ۉs Uم h5]hcIepA?/NBOU$ Nl'7S7ЭA]ɹ;"U}MV`|֯j"jjMRa\m=͂!ۉ XA:72CL2.ܖ5T'{/]
+N[ gpT|Mv^-vb;ؾy؎[uE=L uJVh0I0_=mr'ۉvb{n8YGlWNOݡ_n~Nl'ۉٶ Fٹ,*Џ(a~ˊ 2i7Hw`T\[zvb;}} Fp<82D2>j #"GG;LOrNGMzۉvbFga/ Ynɣi;"jJPS2@)nYnҍB?hj1Gvb;ؾq~GOn^EvtYдWߔZs v hG+ۉvbe9 d4qqnlOf7Tf3^&:V|̨=kkIij?:Nl'7[YmL">.Ө.AC9 arLIiSc\Fz;Nl߸l!`{[hnJM-㮃k1FI0&n/u<&a b;Nll0@$w
+pg9BI~2vb;}#vדRv11EZlH</~^( [TkZإ$oN>ۉvbew:[牎ɬ`,h3].˯A5ǧj)ܐ:$&9@l'7&ۿ~9UZ[.2
+j{hɆ+Q쟞-WF*OVed$HNs({p~6 vb;<iv>Y^0B o;&Szg zʑ˰f,,`cA䐃~&mo'ۉDEMԷ
+oO=yT4}UTvb;\PmT.o9$Y@ᲢHJQFl'ۉ&s4a#=(i,+܍gT<vb;[7))2"NEם 9lvb;R^uZ ;z;zP[8Nl'SSj.+e#ۉ(1eX0`9UZb;NlNVJ|lYr$Nl󤻸O+*8{B{}vb;N)?I?33=zg_x;ZK%ۉNWsz 0zv@d]%ۉvJ@ ό,sӁ@Qh*}Nl'SG:Bfeyv?wvb;RT@m&ɓݽKH0Gs?[Nl l&SE ,`7n<4(%Z2@l״[Vb;DHcN25 Nlx쭣떸OBܧLl_vl]יq@Y_gfk,;W|I
+,t][?vnzMNgҵU ] XzYƘ)5>ĢT\E?,3u/g:$UMB5о6s(e!WSez,;2&%~(Z>o7 Xͤ_:?4pbn.[8]AYɉdBU8iS kG:u^Q_]e՜es [LNd.cԅ,=@>}YÂEaZj>n}weZ>]lX'yvxmGSu/|S9k,h5ut"^P#_z/o7ߵwug[~uC UoU޵stw5T]q[w*IV"/&Yoee!3_1X_:VAmOHU'wTZ!1funhܿݷ;5َ,^
+#on~ue?w=:<bWo%.&`q<rz?l]My_l\O]*=^C}}3f!,0[lGw̻;b 32'my,H}ո3`¼Xl~)ۉk{rvecX0Gp.G!7ݻ,jc]|wjqg[אZrvbv}q fPG%'pYQ 9^X%'򼤀&w-5$:n0L ֓Nl'ۗ}=̷=vcD0BA4y:GPtolaGcg `dJ[vb;VfnX+Ź
+?>g0ok 0b;eb;})'(2i^`f2O'0Y%R BnЎ;=d{vq46b#b;eb;}=:ɔD~Dsi՝J瓱Eo-Kpy+K@{7G=:485yc_ICY`]e}
+%=f)ۉh!X-2E] ~{m»[ gƸ]jd|wrfϫe+bPqeA1>,%YgQX*u!ۉȾzx
+ht؎ѿux1Ua,bI)ۉ+ZkS(֮emPcȲ7Z}'ҖeAط 3v)ۉ+'xeNr}QB65vd${h}SFTv2Sո*j?'91` 't:?UTxXV:s?M!ۉ후Z:V-͹_"sAW; sv<Ht3ѱvžjŵTX՜|hc%oBVrH^sGMF#S&WlFVS_hm`b4‚ArbhsM]הt`K߷6\x;ZC %1''\͒/ vʷ07dpD~h׎O65|eM;?zi~xcMuwW2&צr0.8쯮.dˮ4blHO6|mm9s[
+"»wU>y+LX~bN͗ڥks%#Ѽ}/bfmF1=OZͫۯ@?G.{
+"5G9nQa 2J57w( f${8_O\ Z#Ζke2~uKx0+\O.zZ O7:z4WZ''}'>O*eңόؠc{ءw°Pvk=:84wp[ VI _2!⤕@COm-bblў,9X[r$gF嶰A\;'2_|v-%g
+!' YX趒kkJ޷[M;Rzj乾хd|.KgfFIO:8yt|}_oo}J, ,9M!f\;6-vB>|_CnebTkØ?rΓ[
+ ,bga1"NSY LnI~;܆Dhs[G${@*ٌ)^3.P ."}ɭv7I%ԭ@= l|G'5%I59q $4%c}0sgwN. ̀_76%%n &}3"_rIrrTǥg B_/c5b{ڑ
+ZvelJ3R6fTn}[So-m<]6zs~!_ N(ۉ훍ħZv~ۉԭvۉvb;NlDl'ۉvb;eb;Nl'S&ۉvb;eb;Nl'ۉvb;%b;Nl'ۉvb;NlLl'ۉvvb;NlLl'ۉvb;NlDl'ۉvb;eb;Nl'S&ۉvb;eb;Nl'ۉvb;%b;Nl'ۉvb;NlLl'ۉvvb;NlLl'ۉvb;NlDl'ۉvb;eb;Nl'S&ۉvb;eb;Nl'ۉvb;%b;Nl')ۉvb;2Nl')ۉvb;Nl')ۉvb;Nl'ۉvb;eb;Nl'S&ۉvb;eb;Nl'ۉvb;%b;Nl')ۉvb;2Nl')ۉvb;Nl')ۉvb;NNl'ۉ픉vb;NNl'ۉvb;NNl'ۉvb;Nl')ۉvb;2Nl')ۉvb;Nl')ۉvb;NNl'ۉ픉vb;NNl'ۉvb;NNl'ۉvb;Nl')ۉvb;2Nl')ۉvb;Nl')ۉvb;NNl'ۉ픉vb;NNl'ۉvb;NNl'ۉvvb;NlLl'ۉvvb;Nl'ۉvJvb;Nl'ۉvb;NNl'ۉ픉vb;NNl'ۉvb;NNl'ۉvvb;NlLl'ۉvvb;Nl'ۉvJvb;Nl'S&ۉvb;eb;Nl'S&ۉvb;Nl'S"ۉvb;Nl'ۉvvb;NlLl'ۉvvb;Nl'ۉvJvb;Nl'S&ۉvb;eb;Nl'S&ۉvb;Nl'S"ۉvb;Nl'ۉvvb;NlLl'ۉvvb;Nl'ۉvJvb;Nl'S&ۉvb;eb;Nl'S&ۉvb;Nl'S"ۉvb;2Nl')ۉvb;2Nl'ۉvb;Nl'ۉvb;Nl'S&ۉvb;eb;Nl'S&ۉvb;Nl'S"ۉvb;2Nl')ۉvb;2Nl'ۉaZ[uZ#p۳}lual/_ۅwm|ޮi>NSKlOp]@&=Ut=$;=El_ ۿ|ٍy-u1d푖|Z- /kp_ǖUga6A\s|[F[,{M]m:Maw35&Gޙ~k)hѵ&MI:01ܷZ*A9f*S^Pj7k fx]ψ[&ϢΦ膢͙|thٲvo 4vmNQ^\b"@ ZgnQ7/Zk~ OֵiJדs+s==;z{-ZJ&<Ex_e-nZD{3ۓPEj}ɘ`^վz}={j|}O6㣍B)! ?UZ5oJוvUAl/5lOiƪy^?Z6̞u6ujm
+H޿=k#c5[Ю}gN
+WTO1iܴ@z{njhs':0N=M]/&h޴6Us|ȘmM>hiY$jȡkԈW W ~ uQ$֤w_,>nkTLՈ(QD%J(QD%J(QD%J(QD%J(QD%J(QD%J(QD%J(QD%J(QD%J(QD%J(QDRKi4
+4ZoǧI%J6mRYU]P1E*J<ӣ E+(J\Wm^KΩj\'mj
+TTb^MBi
+ԛ%nMIPx9%'bi4~򘺠+K2- )xFT2M_|qhcRRJx$FTG(5[vn{sݶ귽 U3ɛW26*u+{
+Fyم}do=dz]ꎜ;o9">, D'UFܦS$%z! 0G/S JRt!K2ds (zȡ c*>yư]I8yg7頡eY~׵!s[ )]riXfla=S2y2Hgygg]lik 4zv<5o)"sݸ$َ