Merge lp:~thomas-voss/location-service/snapcraft into lp:location-service/trunk

Proposed by Thomas Voß
Status: Superseded
Proposed branch: lp:~thomas-voss/location-service/snapcraft
Merge into: lp:location-service/trunk
Diff against target: 3106 lines (+2215/-192) (has conflicts)
50 files modified
CMakeLists.txt (+14/-0)
_clang-format (+56/-0)
astyle-config (+43/-0)
debian/changelog (+94/-0)
debian/source/format (+1/-1)
doc/Doxyfile.in (+2/-2)
doc/daemon_and_cli.md (+55/-0)
doc/debugging.md (+92/-0)
doc/hacking.md (+146/-0)
doc/intro.md (+67/-0)
doc/manual_testing.md (+174/-0)
doc/tips_n_tricks.md (+21/-0)
examples/service/service.cpp (+14/-15)
include/location_service/com/ubuntu/location/provider_factory.h (+3/-0)
po/ubuntu-location-service.pot (+7/-11)
snappy/icon.svg (+257/-0)
snappy/snapcraft.yaml (+47/-0)
src/location_service/com/ubuntu/location/CMakeLists.txt (+1/-0)
src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp (+12/-6)
src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h (+12/-0)
src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp (+1/-1)
src/location_service/com/ubuntu/location/engine.cpp (+23/-14)
src/location_service/com/ubuntu/location/engine.h (+3/-3)
src/location_service/com/ubuntu/location/provider_factory.cpp (+14/-0)
src/location_service/com/ubuntu/location/providers/config.cpp (+7/-0)
src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt (+3/-1)
src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp (+42/-0)
src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h (+62/-0)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp (+3/-5)
src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h (+1/-1)
src/location_service/com/ubuntu/location/providers/remote/provider.cpp (+23/-0)
src/location_service/com/ubuntu/location/service/daemon.cpp (+27/-82)
src/location_service/com/ubuntu/location/service/implementation.cpp (+25/-4)
src/location_service/com/ubuntu/location/service/provider_daemon.cpp (+17/-16)
src/location_service/com/ubuntu/location/service/runtime.cpp (+109/-0)
src/location_service/com/ubuntu/location/service/runtime.h (+90/-0)
src/location_service/com/ubuntu/location/service/session/skeleton.cpp (+21/-3)
src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp (+1/-1)
src/location_service/com/ubuntu/location/time_based_update_policy.cpp (+4/-3)
tests/CMakeLists.txt (+2/-0)
tests/acceptance_tests.cpp (+114/-12)
tests/delayed_service_test.cpp (+193/-0)
tests/engine_test.cpp (+3/-3)
tests/gps_provider_test.cpp (+83/-0)
tests/mock_event_receiver.h (+35/-0)
tests/position_test.cpp (+1/-1)
tests/remote_providerd_test.cpp (+1/-7)
tests/runtime_test.cpp (+118/-0)
tools/CMakeLists.txt (+1/-0)
tools/symbol_diff.in (+70/-0)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~thomas-voss/location-service/snapcraft
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+283813@code.launchpad.net

This proposal has been superseded by a proposal from 2016-01-25.

Commit message

Add an initial snapcraft setup.

Description of the change

Add an initial snapcraft setup.

To post a comment you must log in.

Unmerged revisions

216. By Thomas Voß

Add an initial snapcraft setup.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-09-18 23:06:08 +0000
3+++ CMakeLists.txt 2016-01-25 14:24:35 +0000
4@@ -54,6 +54,20 @@
5 SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unused-local-typedefs")
6 endif (DISABLE_ERROR_ON_LOCAL_TYPEDEFS_WARNINGS)
7
8+#
9+# Code style fixer. We rely on clang-format to adjust the formatting of source code.
10+#
11+find_program(CLANG_FORMAT_COMMAND NAMES clang-format-3.6 clang-format-3.5)
12+if (NOT CLANG_FORMAT_COMMAND)
13+ message(WARNING "Cannot find clang-format >= clang-format-3.5: formatcode target will not be available")
14+endif()
15+
16+if (CLANG_FORMAT_COMMAND)
17+ file(GLOB_RECURSE UBUNTU_LOCATION_SERVICE_INTERFACE_HEADER_FILES ${CMAKE_SOURCE_DIR}/include/*.h)
18+ file(GLOB_RECURSE UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_FILES ${CMAKE_SOURCE_DIR}/src/*.h ${CMAKE_SOURCE_DIR}/src/*.cpp)
19+ add_custom_target(formatcode ${CLANG_FORMAT_COMMAND} -i ${UBUNTU_LOCATION_SERVICE_INTERFACE_HEADER_FILES} ${UBUNTU_LOCATION_SERVICE_IMPLEMENTATION_FILES} SOURCES _clang-format)
20+endif()
21+
22 include_directories(
23 ${Boost_INCLUDE_DIRS}
24 ${DBUS_INCLUDE_DIRS}
25
26=== added file '_clang-format'
27--- _clang-format 1970-01-01 00:00:00 +0000
28+++ _clang-format 2016-01-25 14:24:35 +0000
29@@ -0,0 +1,56 @@
30+---
31+Language: Cpp
32+AccessModifierOffset: -4
33+ConstructorInitializerIndentWidth: 4
34+AlignEscapedNewlinesLeft: false
35+AlignTrailingComments: true
36+AllowAllParametersOfDeclarationOnNextLine: true
37+AllowShortBlocksOnASingleLine: false
38+AllowShortIfStatementsOnASingleLine: false
39+AllowShortLoopsOnASingleLine: false
40+AllowShortFunctionsOnASingleLine: All
41+AlwaysBreakTemplateDeclarations: false
42+AlwaysBreakBeforeMultilineStrings: false
43+BreakBeforeBinaryOperators: false
44+BreakBeforeTernaryOperators: true
45+BreakConstructorInitializersBeforeComma: false
46+BinPackParameters: true
47+ColumnLimit: 0
48+ConstructorInitializerAllOnOneLineOrOnePerLine: false
49+DerivePointerAlignment: false
50+ExperimentalAutoDetectBinPacking: false
51+IndentCaseLabels: false
52+IndentWrappedFunctionNames: false
53+IndentFunctionDeclarationAfterType: false
54+MaxEmptyLinesToKeep: 1
55+KeepEmptyLinesAtTheStartOfBlocks: true
56+NamespaceIndentation: None
57+ObjCSpaceAfterProperty: false
58+ObjCSpaceBeforeProtocolList: true
59+PenaltyBreakBeforeFirstCallParameter: 19
60+PenaltyBreakComment: 300
61+PenaltyBreakString: 1000
62+PenaltyBreakFirstLessLess: 120
63+PenaltyExcessCharacter: 1000000
64+PenaltyReturnTypeOnItsOwnLine: 60
65+PointerAlignment: Left
66+SpacesBeforeTrailingComments: 1
67+Cpp11BracedListStyle: true
68+Standard: Cpp11
69+IndentWidth: 4
70+TabWidth: 8
71+UseTab: Never
72+BreakBeforeBraces: Allman
73+SpacesInParentheses: false
74+SpacesInAngles: false
75+SpaceInEmptyParentheses: false
76+SpacesInCStyleCastParentheses: false
77+SpacesInContainerLiterals: true
78+SpaceBeforeAssignmentOperators: true
79+ContinuationIndentWidth: 4
80+CommentPragmas: '^ IWYU pragma:'
81+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
82+SpaceBeforeParens: ControlStatements
83+DisableFormat: false
84+...
85+
86
87=== added file 'astyle-config'
88--- astyle-config 1970-01-01 00:00:00 +0000
89+++ astyle-config 2016-01-25 14:24:35 +0000
90@@ -0,0 +1,43 @@
91+# Options for formatting code with astyle.
92+#
93+# This helps to make code match the style guide.
94+#
95+# Use like this:
96+#
97+# astyle --options=astyle-config mfile.h myfile.cpp
98+#
99+# Occasionally, astyle does something silly (particularly with lambdas), so it's
100+# still necessary to scan the changes for things that are wrong.
101+# But, for most files, it does a good job.
102+#
103+# Please consider using this before checking code in for review. Code reviews shouldn't
104+# have to deal with layout issues, they are just a distraction. It's better to be able
105+# to focus on semantics in a code review, with style issues out of the way.
106+
107+--formatted
108+--style=allman
109+--min-conditional-indent=2
110+--indent-switches
111+--max-instatement-indent=120
112+--pad-header
113+--align-pointer=type
114+--align-reference=type
115+--convert-tabs
116+--close-templates
117+--max-code-length=120
118+
119+# --pad-oper
120+#
121+# Commented out for now. It changes
122+#
123+# for (int i=0; i<10; ++i)
124+# to
125+# for (int i = 0; i < 10; ++i)
126+#
127+# Unfortunately, it also messes with rvalue references:
128+#
129+# ResourcePtr& operator=(ResourcePtr&& r);
130+#
131+# becomes:
132+#
133+# ResourcePtr& operator=(ResourcePtr && r);
134
135=== modified file 'debian/changelog'
136--- debian/changelog 2015-07-27 18:07:37 +0000
137+++ debian/changelog 2016-01-25 14:24:35 +0000
138@@ -1,3 +1,4 @@
139+<<<<<<< TREE
140 location-service (2.1+15.10.20150727-0ubuntu1) wily; urgency=medium
141
142 [ CI Train Bot ]
143@@ -36,6 +37,99 @@
144
145 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 28 May 2015 11:40:58 +0000
146
147+=======
148+location-service (2.1+15.04.20160106-0ubuntu1) vivid; urgency=medium
149+
150+ [ Alberto Mardegan ]
151+ * Set debian source format to "3.0 (native)"
152+
153+ [ Scott Sweeny ]
154+ * Allow providers to register themselves asynchronously (LP: #1415029)
155+
156+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 06 Jan 2016 16:15:29 +0000
157+
158+location-service (2.1+15.04.20151211-0ubuntu1) vivid; urgency=medium
159+
160+ * Account for changes in trust-store w.r.t. assembling the description
161+ of a trust prompt.
162+
163+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 11 Dec 2015 08:57:44 +0000
164+
165+location-service (2.1+15.04.20151209-0ubuntu1) vivid; urgency=medium
166+
167+ * Fix settings not being applied correctly.
168+
169+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 09 Dec 2015 15:22:22 +0000
170+
171+location-service (2.1+15.04.20151202.1-0ubuntu1) vivid; urgency=medium
172+
173+ * Ensure that event connections are cleaned up on destruction. (LP:
174+ #1480877)
175+
176+ -- Thomas Voß <ci-train-bot@canonical.com> Wed, 02 Dec 2015 12:12:21 +0000
177+
178+location-service (2.1+15.04.20151127-0ubuntu1) vivid; urgency=medium
179+
180+ [ Alberto Mardegan ]
181+ * Send last known position on session start
182+
183+ [ CI Train Bot ]
184+ * New rebuild forced.
185+
186+ [ Thomas Voß ]
187+ * Factor out service::Runtime from daemon.cpp into its own .h/.cpp
188+ pair of files. Add test cases around correct operation of
189+ service::Runtime. added:
190+ src/location_service/com/ubuntu/location/service/runtime.cpp
191+ src/location_service/com/ubuntu/location/service/runtime.h
192+ tests/runtime_test.cpp
193+
194+ [ thomas-voss ]
195+ * Factor out service::Runtime from daemon.cpp into its own .h/.cpp
196+ pair of files. Add test cases around correct operation of
197+ service::Runtime. added:
198+ src/location_service/com/ubuntu/location/service/runtime.cpp
199+ src/location_service/com/ubuntu/location/service/runtime.h
200+ tests/runtime_test.cpp
201+
202+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 27 Nov 2015 13:00:33 +0000
203+
204+location-service (2.1+15.04.20151113-0ubuntu1) vivid; urgency=medium
205+
206+ * Adjust default timeout for downloading GPS XTRA data.
207+
208+ -- Thomas Voß <ci-train-bot@canonical.com> Fri, 13 Nov 2015 10:33:56 +0000
209+
210+location-service (2.1+15.04.20151109.2-0ubuntu1) vivid; urgency=medium
211+
212+ [ Alberto Mardegan ]
213+ * Make sure that injected time is given in milliseconds
214+
215+ [ Thomas Voß ]
216+ * Cherry-pick rev. 196 and 199 from lp:location-service. The changes
217+ got accidentally removed by merging the outstanding documentation
218+ branch.
219+ * Handle responses of clients to updates asynchronously. Rely on
220+ dummy::ConnectivityManager as harvesting is disabled anyway. (LP:
221+ #1462664, #1387643)
222+
223+ -- David Barth <david.barth@canonical.com> Mon, 09 Nov 2015 20:48:48 +0000
224+
225+location-service (2.1+15.04.20151022-0ubuntu1) vivid; urgency=medium
226+
227+ [ Thomas Voß ]
228+ * Add documentation for debugging, hacking and debugging the location
229+ service. Pull manual testing instructions over from the wiki. Add
230+ tools for formatting the source.
231+
232+ [ thomas-voss ]
233+ * Add documentation for debugging, hacking and debugging the location
234+ service. Pull manual testing instructions over from the wiki. Add
235+ tools for formatting the source.
236+
237+ -- Thomas Voß <ci-train-bot@canonical.com> Thu, 22 Oct 2015 07:16:50 +0000
238+
239+>>>>>>> MERGE-SOURCE
240 location-service (2.1+15.04.20150427.1-0ubuntu1) vivid; urgency=medium
241
242 [ CI Train Bot ]
243
244=== modified file 'debian/source/format'
245--- debian/source/format 2014-07-30 14:15:06 +0000
246+++ debian/source/format 2016-01-25 14:24:35 +0000
247@@ -1,1 +1,1 @@
248-3.0 (quilt)
249+3.0 (native)
250
251=== modified file 'doc/Doxyfile.in'
252--- doc/Doxyfile.in 2014-05-19 09:55:25 +0000
253+++ doc/Doxyfile.in 2016-01-25 14:24:35 +0000
254@@ -748,7 +748,7 @@
255 # directories that contain image that are included in the documentation (see
256 # the \image command).
257
258-IMAGE_PATH =
259+IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/images
260
261 # The INPUT_FILTER tag can be used to specify a program that doxygen should
262 # invoke to filter for each input file. Doxygen will invoke the filter program
263@@ -1463,7 +1463,7 @@
264 # generate an XML file that captures the structure of
265 # the code including all documentation.
266
267-GENERATE_XML = NO
268+GENERATE_XML = YES
269
270 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
271 # If a relative path is entered the value of OUTPUT_DIRECTORY will be
272
273=== added file 'doc/daemon_and_cli.md'
274--- doc/daemon_and_cli.md 1970-01-01 00:00:00 +0000
275+++ doc/daemon_and_cli.md 2016-01-25 14:24:35 +0000
276@@ -0,0 +1,55 @@
277+# Service Daemon and CLI
278+
279+The location service offers a daemon executable and a corresponding
280+command-line interface for interacting with it. The daemon does not
281+necessarily require root privileges, but might so depending on your
282+configuration.
283+
284+Run the following command to receive an overview of the arguments to
285+the daemon:
286+
287+ ubuntu-location-serviced --help
288+
289+An example invocation of the daemon, configuring a GPS provider that
290+relies on the Android HAL to talk to the chipset, exposing the service
291+on the system DBus instance:
292+
293+ ubuntu-location-serviced --bus system --provider gps::Provider
294+
295+The cli allows for querying properties of a running service instance, e.g.:
296+
297+ ubuntu-location-serviced-cli --bus system --get --property is_online
298+
299+## Configuring an Out-Of-Process Provider
300+
301+If you want to run a provider out of process, the daemon executable
302+allows you to do so by instantiating a so-called remote provider. The
303+following invocation of the service tries to connect to the provider
304+instance described by the given unique DBus name and path.
305+
306+ ubuntu-location-serviced \
307+ --bus system \
308+ --provider remote::Provider \
309+ --remote::Provider::bus=system \
310+ --remote::Provider::name=com.ubuntu.location.provider.Gps \
311+ --remote::Provider::path=/
312+
313+Please note that the service allows for decorating provider names to
314+uniquely identify per provider configuration options and to allow for
315+loading more than one provider of a certain kind. The following
316+configuration configures two remote providers, one relying on GPS
317+(decorated with @gps) and another one relying on network-based
318+positioning (decorated with @network):
319+
320+ ubuntu-location-serviced \
321+ --bus system \
322+ --provider remote::Provider@gps \
323+ --remote::Provider@gps::bus=system \
324+ --remote::Provider@gps::name=com.ubuntu.location.provider.Gps \
325+ --remote::Provider@gps::path=/ \
326+ --provider remote::Provider@network \
327+ --remote::Provider@network::bus=system \
328+ --remote::Provider@network::name=com.ubuntu.location.provider.Network \
329+ --remote::Provider@network::path=/
330+
331+
332
333=== added file 'doc/debugging.md'
334--- doc/debugging.md 1970-01-01 00:00:00 +0000
335+++ doc/debugging.md 2016-01-25 14:24:35 +0000
336@@ -0,0 +1,92 @@
337+# Debugging
338+
339+Location not working? Here's how to debug.
340+
341+## Layers
342+
343+Test in OSMTouch (QML app using Qt API) before testing in webapps or
344+webbrowser app. Different results? File a bug where it doesn't
345+work. Same result of no location? Next step.
346+
347+## Check that stack works with dummy provider
348+
349+Edit /etc/init/ubuntu-location-provider.override to start
350+location-serviced with just the dummy provider; this should
351+work. Doesn't work? File a bug against location-service. Works? Reset
352+config to defaults and try the next thing.
353+
354+## Hardware GPS breaking all of location-service
355+
356+GPS provider is built-in into location-service and might break all of
357+it if it goes south (working on splitting it out); try enabling only
358+the HERE provider on the location-serviced command-line and see if
359+that works. Works? File a bug against location-service. Doesn't work?
360+Move on.
361+
362+## HERE test
363+
364+To test whether the low-level HERE stack gets a location, put
365+http://people.canonical.com/~lool/espoo-cli on your phone (will be
366+included along HERE bits in the future) and run with:
367+
368+ chmod a+x espoo-cli
369+ GLOG_logtostderr=1 GLOG_v=100 LD_LIBRARY_PATH=/custom/vendor/here/location-provider/lib/arm-linux-gnueabihf ./espoo-cli 5
370+
371+NB: 5 is the number of location updates after which the tool exits;
372+updates should come in at approx 15s interval. Output looks like:
373+
374+ I1101 21:30:01.285964 4403 cli.cpp:117] Requested number of updates is 2
375+ I1101 21:30:01.299002 4403 cli.cpp:133] Starting location updates
376+ I1101 21:30:01.301888 4403 cli.cpp:141] Starting GLib main loop
377+ I1101 21:30:11.304612 4403 cli.cpp:158] Location: tstamp=1414891811 lat=xyz long=foo hor. acc.=2569 alt=nan vert. acc.=nan tech=cell
378+ I1101 21:30:11.306061 4403 cli.cpp:170] Remaining updates: 1
379+ I1101 21:30:26.736821 4403 cli.cpp:158] Location: tstamp=1414891826 lat=xyz long=foo hor. acc.=2824 alt=nan vert. acc.=nan tech=cell
380+ I1101 21:30:26.738348 4403 cli.cpp:148] Stopping location updates
381+
382+Low-level HERE stack works but location-serviced with just HERE
383+provider doesn't work? File a bug against espoo projet (HERE) and/or
384+location-service. Low-level HERE stack doesn't work? Move on
385+
386+## location-service and espoo-service debug
387+
388+Collect some debug data by editing /etc/init/ubuntu-espoo-service.conf
389+and /etc/init/ubuntu-location-service.override and changing the start
390+sequence to add some env vars:
391+
392+ export GLOG_v=200
393+ export GLOG_logtostderr=1
394+
395+before the exec. Reboot, and start some app. You should have some log
396+files under /var/log/upstart/ubuntu-espoo-service.log and
397+/var/log/upstart/ubuntu-location-service.log to attach to a bug
398+report; e.g. a working espoo log looks like this:
399+
400+ WARNING: Logging before InitGoogleLogging() is written to STDERR
401+ I1105 16:30:10.221474 1620 provider.cpp:568] StartPositionUpdates
402+ I1105 16:30:10.224901 1620 provider.cpp:122] Successfully started position updates.
403+ I1105 16:30:10.228739 1620 provider.cpp:596] StartVelocityUpdates
404+ I1105 16:30:13.046851 1621 provider.cpp:83] Received location: Position(lat: Coordinate(12.34 deg), lon: Coordinate(12.34 deg), alt: Coordinate(nan m), hor.acc.: 1430 m, ver.acc.: nan m)
405+
406+No position there? check connectivity API works by running:
407+
408+ cd /tmp
409+ wget http://people.ubuntu.com/~lool/connectivity
410+ GLOG_v=200 GLOG_logtostderr=1 ./connectivity
411+
412+you should see something like:
413+
414+ I1105 16:47:26.431466 11140 cached_radio_cell.cpp:160] (mcc: 123, mnc: 2, lac: 1234, id: 123456, asu: 1)
415+ I1105 16:47:26.533818 11140 connectivity.cpp:47] Is wifi enabled: true
416+ I1105 16:47:26.533963 11140 connectivity.cpp:48] Is wifi hw enabled: true
417+ I1105 16:47:26.534010 11140 connectivity.cpp:49] Is wwan enabled: true
418+ I1105 16:47:26.534050 11140 connectivity.cpp:50] Is wwan hw enabled: true
419+ I1105 16:47:26.534442 11140 connectivity.cpp:122] umts(mcc: 123, mnc: 2, lac: 1234, id: 123456, asu: 1)
420+ I1105 16:47:26.534633 11140 connectivity.cpp:155] (bssid: 12:12:12:12:12:12, ssid: xyz, last seen: 1415224046, mode: Mode::infrastructure, frequency: 2442, strength: 63)
421+ I1105 16:47:26.534828 11140 connectivity.cpp:155] (bssid: 12:12:12:12:12:12, ssid: boing, last seen: 1415224046, mode: Mode::infrastructure, frequency: 2467, strength: 57)
422+
423+Also, please attach output of /usr/share/ofono/scripts/list-modems > list-modems-output.txt
424+Please note that the command might take ~1 minute to complete.
425+
426+TODO: document dbus-monitor / d-feet capturing of client / system traffic with snooping config.
427+
428+
429
430=== added file 'doc/hacking.md'
431--- doc/hacking.md 1970-01-01 00:00:00 +0000
432+++ doc/hacking.md 2016-01-25 14:24:35 +0000
433@@ -0,0 +1,146 @@
434+# Hacking
435+
436+
437+## Building the code
438+
439+By default, the code is built in release mode. To build a debug version, use
440+
441+ $ mkdir builddebug
442+ $ cd builddebug
443+ $ cmake -DCMAKE_BUILD_TYPE=debug ..
444+ $ make
445+
446+For a release version, use -DCMAKE_BUILD_TYPE=release
447+
448+## Running the tests
449+
450+ $ make
451+ $ make test
452+
453+Note that "make test" alone is dangerous because it does not rebuild
454+any tests if either the library or the test files themselves need
455+rebuilding. It's not possible to fix this with cmake because cmake cannot
456+add build dependencies to built-in targets. To make sure that everything
457+is up-to-date, run "make" before running "make test"!
458+
459+## Coverage
460+
461+To build with the flags for coverage testing enabled and get coverage:
462+
463+ $ mkdir buildcoverage
464+ $ cd buildcoverage
465+ $ cmake -DCMAKE_BUILD_TYPE=coverage
466+ $ make
467+ $ make test
468+ $ make coverage
469+
470+Unfortunately, it is not possible to get 100% coverage for some files,
471+mainly due to gcc's generation of two destructors for dynamic and non-
472+dynamic instances. For abstract base classes and for classes that
473+prevent stack and static allocation, this causes one of the destructors
474+to be reported as uncovered.
475+
476+There are also issues with some functions in header files that are
477+incorrectly reported as uncovered due to inlining, as well as
478+the impossibility of covering defensive assert(false) statements,
479+such as an assert in the default branch of a switch, where the
480+switch is meant to handle all possible cases explicitly.
481+
482+If you run a binary and get lots of warnings about a "merge mismatch for summaries",
483+this is caused by having made changes to the source that add or remove code
484+that was previously run, so the new coverage output cannot sensibly be merged
485+into the old coverage output. You can get rid of this problem by running
486+
487+ $ make clean-coverage
488+
489+This deletes all the .gcda files, allowing the merge to (sometimes) succeed again.
490+If this doesn't work either, the only remedy is to do a clean build.
491+
492+If lcov complains about unrecognized lines involving '=====',
493+you can patch geninfo and gcovr as explained here:
494+
495+https://bugs.launchpad.net/gcovr/+bug/1086695/comments/2
496+
497+## Code style
498+
499+We use a format tool that fixes a whole lot of issues
500+regarding code style. The formatting changes made by
501+the tool are generally sensible (even though they may not be your
502+personal preference in all cases). If there is a case where the formatting
503+really messes things up, consider re-arranging the code to avoid the problem.
504+The convenience of running the entire code base through the pretty-printer
505+far outweighs any minor glitches with pretty printing, and it means that
506+we get consistent code style for free, rather than endlessly having to
507+watch out for formatting issues during code reviews.
508+
509+As of clang-format-3.7, you can use
510+
511+ // clang-format off
512+ void unformatted_code ;
513+ // clang-format on
514+
515+to suppress formatting for a section of code.
516+
517+To format specific files:
518+
519+ ${CMAKE_BINARY_DIR}/tools/formatcode x.cpp x.h
520+
521+If no arguments are provided, formatcode reads stdin and writes
522+stdout, so you can easily pipe code into the tool from within an
523+editor. For example, to reformat the entire file in vi (assuming
524+${CMAKE_BINARY_DIR}/tools is in your PATH):
525+
526+ 1G!Gformatcode
527+
528+To re-format all source and header files in the tree:
529+
530+ $ make formatcode
531+
532+## Thread and address sanitizer
533+
534+Set SANITIZER to "thread" or "address" to build with the
535+corresponding sanitizer enabled.
536+
537+## Updating symbols file
538+
539+To easily spot new/removed/changed symbols in the library, the debian
540+package maintains a .symbols file that lists all exported symbols
541+present in the library .so. If you add new public symbols to the library,
542+it's necessary to refresh the symbols file, otherwise the package will
543+fail to build. The easiest way to do that is using bzr-builddeb:
544+
545+ $ bzr bd -- -us -uc -j8 # Don't sign source package or changes file, 8 compiles in parallel
546+ $ # this will exit with an error if symbols file isn't up-to-date
547+ $ cd ../build-area/location-service-[version]
548+ $ ./obj-[arch]/tools/symbol_diff
549+
550+This creates a diff of the symbols in /tmp/symbols.diff.
551+(The demangled symbols from the debian build are in ./new_symbols.)
552+
553+Review any changes in /tmp/symbols.diff. If they are OK:
554+
555+ $ cd -
556+ $ patch -p0 < /tmp/symbols.diff
557+
558+## ABI compliance test
559+
560+To use this, install abi-compliance-checker package from the archives.
561+
562+You can use abi-compliance-checker to test whether a particular build
563+is ABI compatible with another build. The tool does some source-level
564+analysis in addition to checking library symbols, so it catches things
565+that are potentially dangerous, but won't be picked up by just looking
566+at the symbol table.
567+
568+Assume you have built devel in src/devel, and you have a later build
569+in src/mybranch and want to check that mybranch is still compatible.
570+To run the compliance test:
571+
572+ $ cd src
573+ $ abi-compliance-checker -lib libunity-scopes.so -old devel/build/test/abi-compliance/abi.xml -new mybranch/build/test/abi-compliance/abi.xml
574+
575+The script will take about two minutes to run. Now point your browser at
576+
577+ src/compat_reports/libunity-scopes.so/[version]_to_[version]/compat_report.html
578+
579+The report provides a nicely layed-out page with all the details.
580
581=== added directory 'doc/images'
582=== added file 'doc/images/LocationServiceHighLevel.png'
583Binary files doc/images/LocationServiceHighLevel.png 1970-01-01 00:00:00 +0000 and doc/images/LocationServiceHighLevel.png 2016-01-25 14:24:35 +0000 differ
584=== added file 'doc/intro.md'
585--- doc/intro.md 1970-01-01 00:00:00 +0000
586+++ doc/intro.md 2016-01-25 14:24:35 +0000
587@@ -0,0 +1,67 @@
588+# Introduction {#mainpage}
589+
590+Ubuntu's location service is a central hub for multiplexing access to
591+positioning subsystems available via hard- and software. It provides a
592+client API offering positioning capabilities to applications and other
593+system components, abstracting away the details of individual
594+positioning solutions.
595+
596+## Vocabulary
597+
598+To make the remainder of this documentation as easily understandable
599+as possible, we start over with introducing some vocabulary:
600+
601+- Engine:
602+ Responsible for handling input from multiple positioning
603+ subsystems and maintaining the state of the overall system. Think
604+ about it like the heart of the system.
605+
606+- Provider:
607+ A positioning subsystem that feeds into the positioning
608+ engine. Common examples are a GPS provider or a network-based
609+ positioning provider.
610+
611+- Service:
612+ The point of entry for applications and services that would
613+ like to receive position data.
614+
615+- Session:
616+ In order to receive position information, every application
617+ or service has to create a session with the location Service.
618+
619+- Update: An update is a timestamped entity to a certain type of data.
620+
621+- [WGS84, http://en.wikipedia.org/wiki/World_Geodetic_System]: The coordinate system that is used throughout the entire location subsystem.
622+
623+## Architectural Overview
624+
625+The high-level architecture of the service is shown in the following diagram:
626+
627+![High-level architectural overview](images/LocationServiceHighLevel.png)
628+
629+In this diagram, the configuration of the engine refers to:
630+
631+ * The current state of any satellite-based positioning subsystems. Can either be off or on.
632+ * The current state of reporting facilities responsible for harvesting wifi and cell id measurements together with location information and sending them off to remote services. Can either be off or on.
633+ * The overall state of the engine. Can either be off, on or active.
634+
635+The Service takes this configuration and exposes it to client
636+applications. In addition, mainly for debugging purposes, the set of
637+currently visible satellites (if any) is maintained and exposed to
638+privileged client applications.
639+
640+## Privacy & Access Control
641+
642+Location information is highly privacy relevant. For this reason, the
643+location service is deeply integrated with AppArmor and Ubuntu's
644+overall trust infrastructure. Every incoming session request is
645+validated and if in doubt, the user is asked to explicitly grant trust
646+to the application requesting access to positioning
647+information. Please see [@ref com::ubuntu::location::service::PermissionManager]
648+for further details.
649+
650+In addition, the location service allows for selectively adjusting the
651+accuracy and reporting setup of the location Engine to provide further
652+fine-grained control over the exposed data to user. Within this setup,
653+a user is able to entirely disable all positioning.
654+
655
656=== added file 'doc/manual_testing.md'
657--- doc/manual_testing.md 1970-01-01 00:00:00 +0000
658+++ doc/manual_testing.md 2016-01-25 14:24:35 +0000
659@@ -0,0 +1,174 @@
660+# Manual Testplan
661+
662+[TOC]
663+
664+While the automatic test suite of the location service is
665+comprehensive and covers large parts of the functionality of the
666+service itself, we still provide an additional level of acceptance
667+testing covering the entire location stack/experience as a part of
668+this document.
669+
670+## Dependents/Clients
671+
672+ - qtubuntu-sensors
673+ - Qt/QML applications:
674+ - Browser
675+ - osmTouch
676+
677+## Test Plan
678+
679+This test plan is not supposed to be complete; use it to guide your
680+manual testing so you don't miss big functional areas that are part of
681+the component; also this should be used as guideline to inspire the
682+exploratory testing which should be adapted smartly based on the real
683+content of a MP.
684+
685+Please note that if you're testing the GPS provider, the location
686+service relies on GPS hardware to obtain a location fix. For that, it
687+might be required that you execute the manual steps listed before
688+close to a window or ideally outside, with good satellite visibility
689+conditions.
690+
691+__Note: It can take up to 15 minutes for the GPS device to get a lock, due to lack of assisted GPS__
692+
693+ - Install latest image on phone
694+ - Install freshly built MPs that are needed for landing
695+
696+Depending on the default configuration of location-service on the
697+image, you may skip parts of this test plan. E.g. if GPS hardware is
698+disabled, skip this part. You can see which providers are enabled by
699+looking at the list of providers on the location-serviced command-line
700+(`ps fauxw | grep location-service`, then look at the `--provider`
701+flags).
702+
703+### Dummy provider
704+
705+This tests forces location-service to use only the dummy provider;
706+this providers a baseline test for the app to trust-store to
707+location-service path.
708+
709+ - phablet-shell into the phone:
710+ - `sudo service ubuntu-location-service stop && sudo /usr/bin/ubuntu-location-serviced --bus system --provider dummy::Provider --dummy::Provider::ReferenceLocationLat=48.857503 --dummy::Provider::ReferenceLocationLon=2.295072`
711+ - As phablet, start the trust store again (it stops when location-service is stopped) with: `start ubuntu-location-service-trust-stored`
712+ - Ensure that all AP tests for the webbrowser pass as expected
713+ - Point the browser to maps.google.com (alternatively: here.com, maps.bing.fr).
714+ - Request centering the map on current position and observe if it works correctly (should show the Eiffel tower)
715+ - Install osmTouch from the app store
716+ - Launch osmTouch and check if it centers on the Eiffel tower.
717+ - Install a maps webapp such as HERE or Google Maps webapp from the app store
718+ - Launch maps webapp and check if it centers on the Eiffel tower.
719+
720+### GPS Test Plan
721+
722+This applies only if GPS provider is enabled.
723+
724+ - (If applicable: Remember to add the silo you are testing)
725+ - `sudo apt-get install ubuntu-location-service-tests`
726+ - If you want to send off crowdsourced information, i.e., information about visible wifis and visible radio cells for the obtained location fixes to Mozilla's location service and our own instance:
727+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_ENABLE_HARVESTING_DURING_TESTS=1 /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_without_supl_benchmark_requires_hardware`
728+ - If you '''don't''' want to send off crowdsourced information:
729+ - `sudo GLOG_v=40 GLOG_logtostderr=1 /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_without_supl_benchmark_requires_hardware`
730+
731+ - The test will output a lot of diagnostic information to the
732+ terminal and will take ~30 minutes. If satellite visibility is
733+ limited, it can take even longer. The test will automatically
734+ report success or failure.
735+
736+### Preliminary AGPS Test Plan
737+
738+**Does not apply to Krillin**
739+
740+Please note that the Krillin GPS chipset driver and its integration
741+within Ubuntu does not support vanilla AGPS (i.e., SUPL) right
742+now. For that, this test case is irrelevant for Krillin and is likely
743+to fail.
744+
745+This applied only if GPS provider and some other provider (giving
746+_A_ssistance) are enabled.
747+
748+ - Add the silo.
749+ - `sudo apt-get install ubuntu-location-service-tests`
750+ - Obtain a (rough) location estimate for your current location on Google maps.
751+ - Make sure to replace INSERT_ESTIMATE_HERE with the respective
752+ values obtained from Google maps.
753+ - If you want to send off crowdsourced information, i.e., information
754+ about visible wifis and visible radio cells for the obtained
755+ location fixes to Mozilla's location service and our own instance:
756+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_ENABLE_HARVESTING_DURING_TESTS=1 GPS_TEST_REF_LAT=INSERT_ESTIMATE_HERE GPS_TEST_REF_LON=INSERT_ESTIMATE_HERE /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_with_supl_benchmark_requires_hardware`
757+ - If you '''don't''' want to send off crowdsourced information:
758+ - `sudo GLOG_v=40 GLOG_logtostderr=1 GPS_TEST_REF_LAT=INSERT_ESTIMATE_HERE GPS_TEST_REF_LON=INSERT_ESTIMATE_HERE /usr/bin/uls-tests/gps_provider_test --gtest_filter=*.time_to_first_fix_cold_start_with_supl_benchmark_requires_hardware`
759+
760+ - The test will output a lot of diagnostic information to the
761+ terminal and will take ~10 minutes or less. The test will
762+ automatically report success or failure.
763+
764+### Espoo / HERE provider
765+
766+This applies only if the Espoo / HERE remote provider is enabled. This
767+provider should be enabled by default and may either work standalone
768+as the only provider or as an assistance for the GPS hardware to lock.
769+
770+ - Add the silo; special exception for lxc-android-config: see https://wiki.ubuntu.com/Touch/Testing/lxc-android-config
771+ - If noted, deploy an updated custom tarball:
772+ - Download the tarball under /tmp ('''NOT''' under /)
773+ - Unpack there: `cd /tmp; sudo tar xvf custom-vendor-here-*.tar.xz`
774+ - Remove older bits: `sudo rm -rf /custom/vendor/here/`
775+ - Update custom bits: `sudo mv /tmp/system/custom/vendor/here /custom/vendor`
776+ - Reboot
777+ - After boot, check you have these three processes running on top of location-service:
778+ - slpgwd
779+ - posclientd
780+ - ubuntu-espoo-service
781+ - Make sure SIM is unlocked and attached to the network (has some reliable signal) and that WiFi is turned on.
782+ - Install OSMTouch app
783+ - Run OSMTouch app, hit the position button every other second until you get a blue circle showing your current location;
784+
785+# Connectivity API
786+
787+For integration of network-based positioning providers, the location
788+service offers a connectivity API that provides access to wifi and
789+cell measurements as well as information on the current overall
790+connectivity status of the device. Please execute the following
791+commands on a newly flashed device with a writable image:
792+
793+ - `sudo apt-get update && sudo apt-get build-dep location-service && sudo apt-get install libubuntu-location-service-dev ubuntu-location-service-examples`
794+ - `mkdir /tmp/build && cd /tmp/build && cmake /usr/share/ubuntu-location-service/examples/standalone/connectivity/ && make`
795+ - `GLOG_logtostderr=1 ./connectivity`
796+
797+Verify that the output looks similar to:
798+
799+ phablet@ubuntu-phablet:/tmp/build$ ./connectivity
800+ Is wifi enabled: true
801+ Is wifi hw enabled: true
802+ Is wwan enabled: false
803+ Is wwan hw enabled: true
804+ umts(mcc: 262, mnc: 2, lac: 5313, id: 131948771, asu: 7)
805+ (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2462, strength: 72)
806+ (bssid: 00:22:3F:35:43:58, ssid: JustAnotherWLAN, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2412, strength: 24)
807+ (bssid: 82:C7:A6:40:8C:4E, ssid: EasyBox-44D054, last seen: 1408955206, mode: Mode::infrastructure, frequency: 2417, strength: 17)
808+ (bssid: 00:24:01:B8:32:8D, ssid: gra, last seen: 1408955086, mode: Mode::infrastructure, frequency: 2412, strength: 12)
809+ (bssid: C0:25:06:3C:28:22, ssid: FRITZ!Box 6360 Cable, last seen: 1408954966, mode: Mode::infrastructure, frequency: 2412, strength: 17)
810+ (bssid: 00:1C:4A:A5:B7:59, ssid: FRITZ!Box Fon WLAN 7170, last seen: 1408954966, mode: Mode::infrastructure, frequency: 2437, strength: 10)
811+ Last seen changed for wifi (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2462, strength: 72)
812+ Last seen changed for wifi (bssid: 00:22:3F:35:43:58, ssid: JustAnotherWLAN, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2412, strength: 24)
813+ Signal strength changed for wifi: (bssid: BC:F2:AF:AF:19:A2, ssid: devolo-bcf2afaf19a2, last seen: 1408955257, mode: Mode::infrastructure, frequency: 2462, strength: 73)
814+
815+# Trust Store Integration
816+
817+Please note that we are assuming a freshly wiped system for testing
818+here. If you cannot fulfill that pre-condition, please run `rm -rf
819+/home/phablet/.local/share/UbuntuLocationService && sudo shutdown -r` prior to running the
820+tests:
821+
822+## Unconfined
823+
824+ - Open the browser, go to maps.google.com
825+ - Observe the in-browser dialog asking for granting access to location.
826+
827+## Confined Web-App
828+
829+ - Open the Nokia Here web app, observe the trust dialog appearing.
830+
831+## Confined Application
832+
833+ - Open osmtouch and observe the osmtouch surface sliding up, presenting you with a trust dialog.
834
835=== added file 'doc/tips_n_tricks.md'
836--- doc/tips_n_tricks.md 1970-01-01 00:00:00 +0000
837+++ doc/tips_n_tricks.md 2016-01-25 14:24:35 +0000
838@@ -0,0 +1,21 @@
839+# Tips'n'Tricks
840+
841+## Mark HERE license as accepted from cmdline
842+
843+ sudo LC_ALL=C gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Set com.ubuntu.location.providers.here.AccountsService LicenseAccepted '<true>'
844+
845+## Force startup after ofono and NM are started
846+
847+This is a *workaround* to get connectivity API to collect; mount your
848+system read-write and edit
849+/etc/init/ubuntu-location-provider-here-slpgwd.conf:
850+
851+ sudo mount -o remount,rw /
852+ sudo vi /etc/init/ubuntu-location-provider-here-slpgwd.conf
853+
854+change: `start on started dbus and (started ofono or started network-manager)`
855+to: `start on started dbus and started ofono and started network-manager`
856+
857+ sudo mount -o remount,ro /
858+ sync
859+ sudo reboot
860
861=== modified file 'examples/service/service.cpp'
862--- examples/service/service.cpp 2014-11-14 11:26:45 +0000
863+++ examples/service/service.cpp 2016-01-25 14:24:35 +0000
864@@ -99,7 +99,10 @@
865 auto selected_providers = options.value_for_key<std::vector<std::string>>("provider");
866
867 std::map<std::string, cul::ProviderFactory::Configuration> config_lut;
868- std::set<cul::Provider::Ptr> instantiated_providers;
869+
870+ culs::DefaultConfiguration config;
871+ auto settings = std::make_shared<cul::BoostPtreeSettings>(options.value_for_key<std::string>("config-file"));
872+ auto engine = config.the_engine(std::set<cul::Provider::Ptr>{}, config.the_provider_selection_policy(), settings);
873
874 for (const std::string& provider : selected_providers)
875 {
876@@ -129,15 +132,15 @@
877
878 try
879 {
880- auto p = cul::ProviderFactory::instance().create_provider_for_name_with_config(
881- provider,
882- config_lut[provider]);
883-
884- if (p)
885- instantiated_providers.insert(p);
886- else
887- throw std::runtime_error("Problem instantiating provider");
888-
889+ auto result = std::async(std::launch::async, [provider, config_lut, engine] {
890+ return cul::ProviderFactory::instance().create_provider_for_name_with_config(
891+ provider,
892+ config_lut.at(provider),
893+ [engine](cul::Provider::Ptr provider)
894+ {
895+ engine->add_provider(provider);
896+ });
897+ });
898 } catch(const std::runtime_error& e)
899 {
900 std::cerr << "Exception instantiating provider: " << e.what() << " ... Aborting now." << std::endl;
901@@ -163,15 +166,11 @@
902 };
903 outgoing->install_executor(dbus::asio::make_executor(outgoing));
904
905- auto settings = std::make_shared<cul::BoostPtreeSettings>(options.value_for_key<std::string>("config-file"));
906-
907- culs::DefaultConfiguration config;
908-
909 culs::Implementation::Configuration configuration
910 {
911 incoming,
912 outgoing,
913- config.the_engine(instantiated_providers, config.the_provider_selection_policy(), settings),
914+ engine,
915 config.the_permission_manager(incoming),
916 culs::Harvester::Configuration
917 {
918
919=== modified file 'include/location_service/com/ubuntu/location/provider_factory.h'
920--- include/location_service/com/ubuntu/location/provider_factory.h 2014-10-27 21:58:16 +0000
921+++ include/location_service/com/ubuntu/location/provider_factory.h 2016-01-25 14:24:35 +0000
922@@ -54,6 +54,9 @@
923 // --provider=remote::Provider@gps --remote::Provider@gps::name="com.ubuntu.android.gps.Provider" --remote::Provider@gps::path="/com/ubuntu/android/gps/Provider"
924 Provider::Ptr create_provider_for_name_with_config(const std::string& name, const Configuration& config);
925
926+ // Async version of above.
927+ void create_provider_for_name_with_config(const std::string& name, const Configuration& config, const std::function<void(Provider::Ptr)>& cb);
928+
929 void enumerate(const std::function<void(const std::string&, const Factory&)>& enumerator);
930
931 private:
932
933=== modified file 'po/ubuntu-location-service.pot'
934--- po/ubuntu-location-service.pot 2014-09-19 09:06:30 +0000
935+++ po/ubuntu-location-service.pot 2016-01-25 14:24:35 +0000
936@@ -1,13 +1,14 @@
937-# Copyright (C) 2014 Canonical Ltd.
938-# This file is distributed under the same license as the ubuntu-location-service package.
939-# Thomas Voß <thomas.voss@canonical.com>, 2014.
940+# SOME DESCRIPTIVE TITLE.
941+# Copyright (C) YEAR Canonical Ltd.
942+# This file is distributed under the same license as the PACKAGE package.
943+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
944 #
945 #, fuzzy
946 msgid ""
947 msgstr ""
948 "Project-Id-Version: ubuntu-location-service\n"
949 "Report-Msgid-Bugs-To: \n"
950-"POT-Creation-Date: 2014-09-19 01:04+0200\n"
951+"POT-Creation-Date: 2015-11-27 14:07+0100\n"
952 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
953 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
954 "Language-Team: LANGUAGE <LL@li.org>\n"
955@@ -16,11 +17,6 @@
956 "Content-Type: text/plain; charset=CHARSET\n"
957 "Content-Transfer-Encoding: 8bit\n"
958
959-#: /tmp/i18n/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:170
960-msgid "An unconfined application wants to access your current location."
961-msgstr ""
962-
963-#: /tmp/i18n/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:173
964-#, boost-format
965-msgid "%1% wants to access your current location."
966+#: /home/tvoss/ubuntu/scratch/fix-prompt-string/src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp:149
967+msgid "wants to access your current location."
968 msgstr ""
969
970=== added directory 'snappy'
971=== added file 'snappy/icon.svg'
972--- snappy/icon.svg 1970-01-01 00:00:00 +0000
973+++ snappy/icon.svg 2016-01-25 14:24:35 +0000
974@@ -0,0 +1,257 @@
975+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
976+<!-- Created with Inkscape (http://www.inkscape.org/) -->
977+<svg
978+ xmlns:svg="http://www.w3.org/2000/svg"
979+ xmlns="http://www.w3.org/2000/svg"
980+ version="1.0"
981+ width="800"
982+ height="800"
983+ id="svg2">
984+ <defs
985+ id="defs4" />
986+ <g
987+ id="layer1">
988+ <g
989+ id="g4091">
990+ <g
991+ transform="translate(100,100)"
992+ id="g3635">
993+ <g
994+ id="g3434">
995+ <path
996+ d="M 248.90172,43.111591 L 351.09828,556.88841"
997+ id="path3418"
998+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
999+ <path
1000+ d="M 154.48441,82.220522 L 445.51559,517.77948"
1001+ id="path3420"
1002+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1003+ <path
1004+ d="M 82.220526,154.4844 L 517.77947,445.5156"
1005+ id="path3422"
1006+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1007+ <path
1008+ d="M 43.111592,248.90171 L 556.8884,351.09829"
1009+ id="path3424"
1010+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1011+ <path
1012+ d="M 43.111588,351.09827 L 556.8884,248.90173"
1013+ id="path3426"
1014+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1015+ <path
1016+ d="M 82.220515,445.51558 L 517.77947,154.48442"
1017+ id="path3428"
1018+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1019+ <path
1020+ d="M 154.48439,517.77946 L 445.51559,82.220536"
1021+ id="path3430"
1022+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1023+ <path
1024+ d="M 248.9017,556.88839 L 351.09828,43.111601"
1025+ id="path3432"
1026+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1027+ </g>
1028+ <g
1029+ id="g3631">
1030+ <path
1031+ d="M 195.25,47.125 L 231.6875,196 L 265.96875,221.125 L 266.34375,218.71875 L 195.25,47.125 z M 404.75,47.125 L 326.96875,175.3125 L 333.65625,218.71875 L 404.75,47.125 z M 47.125,195.25 L 175.3125,273.03125 L 218.71875,266.34375 L 47.125,195.25 z M 552.875,195.25 L 404,231.6875 L 378.875,265.96875 L 381.28125,266.34375 L 552.875,195.25 z M 424.6875,326.96875 L 381.28125,333.65625 L 552.875,404.75 L 424.6875,326.96875 z M 218.75,333.65625 L 47.125,404.75 L 195.96875,368.3125 L 221.125,334.03125 L 218.75,333.65625 z M 334.03125,378.875 L 333.65625,381.28125 L 404.75,552.875 L 368.3125,404 L 334.03125,378.875 z M 266.34375,381.28125 L 195.25,552.875 L 273.03125,424.6875 L 266.34375,381.28125 z"
1032+ id="path3398"
1033+ style="fill:#b3b3b3;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1034+ <path
1035+ d="M 195.25,47.125 L 266.34375,218.71875 L 273.03125,175.3125 L 195.25,47.125 z M 404.75,47.125 L 333.65625,218.71875 L 334.03125,221.125 L 368.3125,196 L 404.75,47.125 z M 47.125,195.25 L 218.71875,266.34375 L 221.125,265.96875 L 196,231.6875 L 47.125,195.25 z M 552.875,195.25 L 381.28125,266.34375 L 424.6875,273.03125 L 552.875,195.25 z M 175.3125,326.96875 L 47.125,404.75 L 218.75,333.65625 L 175.3125,326.96875 z M 381.28125,333.65625 L 378.875,334.03125 L 404,368.3125 L 552.875,404.75 L 381.28125,333.65625 z M 265.96875,378.875 L 231.6875,404 L 195.25,552.875 L 266.34375,381.28125 L 265.96875,378.875 z M 333.65625,381.28125 L 326.96875,424.6875 L 404.75,552.875 L 333.65625,381.28125 z"
1036+ id="path3408"
1037+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1038+ </g>
1039+ <g
1040+ id="g3627">
1041+ <path
1042+ d="M 97.8125,97.8125 L 221.15625,265.96875 L 260,260 L 97.8125,97.8125 z M 502.1875,97.8125 L 334.03125,221.15625 L 340,260 L 502.1875,97.8125 z M 378.84375,334.03125 L 340,340 L 502.1875,502.1875 L 378.84375,334.03125 z M 260,340 L 97.8125,502.1875 L 265.96875,378.84375 L 260,340 z"
1043+ id="path3258"
1044+ style="fill:#666666;fill-rule:evenodd;stroke:#000000;stroke-width:3.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1045+ <path
1046+ d="M 97.8125,97.8125 L 260,260 L 265.96875,221.15625 L 97.8125,97.8125 z M 502.1875,97.8125 L 340,260 L 378.84375,265.96875 L 502.1875,97.8125 z M 221.125,334.03125 L 97.8125,502.1875 L 260,340 L 221.125,334.03125 z M 340,340 L 334.03125,378.84375 L 502.1875,502.1875 L 340,340 z"
1047+ id="path3268"
1048+ style="fill:#ececec;fill-rule:evenodd;stroke:#000000;stroke-width:3.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1049+ </g>
1050+ <g
1051+ id="g3623">
1052+ <path
1053+ d="M 300,0 L 260,260 L 300,300 L 300,0 z M 300,300 L 600,300 L 340,260 L 300,300 z M 300,300 L 300,600 L 340,340 L 300,300 z M 300,300 L 0,300 L 260,340 L 300,300 z"
1054+ id="path3171"
1055+ style="fill:#1a1a1a;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1056+ <path
1057+ d="M 300,0 L 300,300 L 340,260 L 300,0 z M 300,300 L 340,340 L 600,300 L 300,300 z M 300,300 L 260,340 L 300,600 L 300,300 z M 300,300 L 260,260 L 0,300 L 300,300 z"
1058+ id="path3179"
1059+ style="fill:#b3b3b3;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
1060+ </g>
1061+ </g>
1062+ <g
1063+ id="g4053">
1064+ <g
1065+ id="g3955">
1066+ <path
1067+ d="M 595.7663,184.82916 L 595.7663,182.46588 L 599.49677,182.46588 L 599.49677,158.03229 L 595.7663,158.03229 L 595.7663,155.66901 L 604.88739,155.66901 L 622.48505,176.31354 L 622.48505,158.03229 L 618.77411,158.03229 L 618.77411,155.66901 L 628.96942,155.66901 L 628.96942,158.03229 L 625.23895,158.03229 L 625.23895,184.82916 L 620.12177,184.82916 L 602.25067,163.75494 L 602.25067,182.46588 L 605.96161,182.46588 L 605.96161,184.82916 L 595.7663,184.82916 z M 647.97333,183.03229 C 650.46029,183.03229 652.30924,181.98411 653.5202,179.88776 C 654.73112,177.79141 655.33658,174.58829 655.33661,170.27838 C 655.33658,165.95548 654.73112,162.74585 653.5202,160.64948 C 652.30924,158.55315 650.46029,157.50497 647.97333,157.50494 C 645.49935,157.50497 643.65365,158.56291 642.43622,160.67877 C 641.21876,162.79468 640.61004,165.99455 640.61005,170.27838 C 640.61004,174.54922 641.21876,177.74258 642.43622,179.85846 C 643.65365,181.97435 645.49935,183.03229 647.97333,183.03229 L 647.97333,183.03229 z M 647.97333,185.39557 C 643.06446,185.39557 639.21681,184.05442 636.43036,181.37213 C 633.6439,178.68985 632.25067,174.99193 632.25067,170.27838 C 632.25067,165.56486 633.64715,161.86369 636.44012,159.17487 C 639.23308,156.48609 643.07748,155.14169 647.97333,155.14166 C 652.88216,155.14169 656.72981,156.48284 659.5163,159.1651 C 662.30272,161.84741 663.69595,165.55184 663.69598,170.27838 C 663.69595,174.99193 662.29947,178.68985 659.50653,181.37213 C 656.71354,184.05442 652.86914,185.39557 647.97333,185.39557 L 647.97333,185.39557 z"
1068+ id="text3671"
1069+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1070+ <path
1071+ d="M 600.47913,642.88086 L 600.47913,635.9668 L 602.95959,635.9668 C 603.33719,638.1543 604.22912,639.78842 605.63538,640.86914 C 607.04162,641.94987 608.98823,642.49024 611.47522,642.49023 C 613.49343,642.49024 615.02989,642.10612 616.08459,641.33789 C 617.13926,640.56967 617.66661,639.44336 617.66663,637.95898 C 617.66661,636.78712 617.30853,635.87566 616.59241,635.22461 C 615.87624,634.57358 614.39838,633.96811 612.15881,633.4082 L 607.78381,632.33398 C 604.93224,631.60483 602.92704,630.59246 601.76819,629.29688 C 600.60933,628.00132 600.0299,626.15562 600.02991,623.75977 C 600.0299,620.86916 600.99019,618.61982 602.91077,617.01172 C 604.83133,615.40367 607.52339,614.59964 610.98694,614.59961 C 612.69265,614.59964 614.46674,614.74287 616.3092,615.0293 C 618.15163,615.31578 620.06244,615.74547 622.04163,616.31836 L 622.04163,622.76367 L 619.56116,622.76367 C 619.18353,620.75849 618.35671,619.29039 617.08069,618.35938 C 615.80463,617.42841 613.98822,616.96292 611.63147,616.96289 C 609.70437,616.96292 608.2493,617.2982 607.26624,617.96875 C 606.28315,618.63935 605.79162,619.6387 605.79163,620.9668 C 605.79162,622.17776 606.13016,623.09898 606.80725,623.73047 C 607.48432,624.362 609.14448,625.0163 611.78772,625.69336 L 616.16272,626.76758 C 618.87103,627.44468 620.83392,628.49936 622.05139,629.93164 C 623.26881,631.36395 623.87754,633.3366 623.87756,635.84961 C 623.87754,638.79232 622.86191,641.02865 620.83069,642.55859 C 618.79942,644.08854 615.81114,644.85352 611.86584,644.85352 C 609.96479,644.85352 608.07677,644.69075 606.20178,644.36523 C 604.32678,644.03971 602.41923,643.54492 600.47913,642.88086 L 600.47913,642.88086 z M 643.70178,642.49023 C 646.18874,642.49024 648.0377,641.44206 649.24866,639.3457 C 650.45957,637.24936 651.06504,634.04623 651.06506,629.73633 C 651.06504,625.41343 650.45957,622.2038 649.24866,620.10742 C 648.0377,618.01109 646.18874,616.96292 643.70178,616.96289 C 641.22781,616.96292 639.38211,618.02086 638.16467,620.13672 C 636.94721,622.25263 636.33849,625.45249 636.3385,629.73633 C 636.33849,634.00717 636.94721,637.20053 638.16467,639.31641 C 639.38211,641.43229 641.22781,642.49024 643.70178,642.49023 L 643.70178,642.49023 z M 643.70178,644.85352 C 638.79292,644.85352 634.94526,643.51237 632.15881,640.83008 C 629.37235,638.14779 627.97912,634.44988 627.97913,629.73633 C 627.97912,625.02281 629.37561,621.32164 632.16858,618.63281 C 634.96154,615.94404 638.80594,614.59964 643.70178,614.59961 C 648.61061,614.59964 652.45827,615.94078 655.24475,618.62305 C 658.03118,621.30536 659.42441,625.00978 659.42444,629.73633 C 659.42441,634.44988 658.02792,638.14779 655.23499,640.83008 C 652.44199,643.51237 648.59759,644.85352 643.70178,644.85352 L 643.70178,644.85352 z"
1072+ id="text3675"
1073+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1074+ <path
1075+ d="M 134.89001,642.88251 L 134.89001,635.96844 L 137.37048,635.96844 C 137.74808,638.15595 138.64001,639.79006 140.04626,640.87079 C 141.45251,641.95152 143.39912,642.49188 145.88611,642.49188 C 147.90432,642.49188 149.44078,642.10777 150.49548,641.33954 C 151.55015,640.57131 152.07749,639.44501 152.07751,637.96063 C 152.07749,636.78876 151.71942,635.87731 151.0033,635.22626 C 150.28713,634.57523 148.80927,633.96976 146.5697,633.40985 L 142.1947,632.33563 C 139.34313,631.60648 137.33793,630.59411 136.17908,629.29852 C 135.02022,628.00297 134.44079,626.15727 134.4408,623.76141 C 134.44079,620.87081 135.40108,618.62147 137.32166,617.01337 C 139.24222,615.40532 141.93428,614.60129 145.39783,614.60126 C 147.10354,614.60129 148.87763,614.74452 150.72009,615.03094 C 152.56252,615.31743 154.47333,615.74712 156.45251,616.32001 L 156.45251,622.76532 L 153.97205,622.76532 C 153.59442,620.76014 152.7676,619.29204 151.49158,618.36102 C 150.21552,617.43006 148.39911,616.96457 146.04236,616.96454 C 144.11526,616.96457 142.66019,617.29985 141.67712,617.9704 C 140.69404,618.641 140.20251,619.64034 140.20251,620.96844 C 140.20251,622.1794 140.54105,623.10063 141.21814,623.73212 C 141.89521,624.36365 143.55537,625.01794 146.19861,625.69501 L 150.57361,626.76923 C 153.28192,627.44633 155.24481,628.50101 156.46228,629.93329 C 157.6797,631.36559 158.28843,633.33825 158.28845,635.85126 C 158.28843,638.79397 157.2728,641.0303 155.24158,642.56024 C 153.21031,644.09019 150.22203,644.85516 146.27673,644.85516 C 144.37568,644.85516 142.48766,644.6924 140.61267,644.36688 C 138.73766,644.04136 136.83011,643.54657 134.89001,642.88251 L 134.89001,642.88251 z M 194.79236,644.28876 L 189.7533,644.28876 L 183.15173,623.05829 L 176.55017,644.28876 L 171.51111,644.28876 L 163.1908,617.49188 L 160.35876,617.49188 L 160.35876,615.1286 L 174.18689,615.1286 L 174.18689,617.49188 L 171.06189,617.49188 L 176.6283,635.40204 L 182.91736,615.1286 L 188.46423,615.1286 L 194.87048,635.73407 L 200.55408,617.49188 L 197.07751,617.49188 L 197.07751,615.1286 L 206.10095,615.1286 L 206.10095,617.49188 L 203.11267,617.49188 L 194.79236,644.28876 z"
1076+ id="text3679"
1077+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1078+ <path
1079+ d="M 130.16917,184.84395 L 130.16917,182.48067 L 133.89964,182.48067 L 133.89964,158.04707 L 130.16917,158.04707 L 130.16917,155.68379 L 139.29027,155.68379 L 156.88792,176.32832 L 156.88792,158.04707 L 153.17699,158.04707 L 153.17699,155.68379 L 163.3723,155.68379 L 163.3723,158.04707 L 159.64183,158.04707 L 159.64183,184.84395 L 154.52464,184.84395 L 136.65355,163.76973 L 136.65355,182.48067 L 140.36449,182.48067 L 140.36449,184.84395 L 130.16917,184.84395 z M 199.05589,184.84395 L 194.01683,184.84395 L 187.41527,163.61348 L 180.81371,184.84395 L 175.77464,184.84395 L 167.45433,158.04707 L 164.6223,158.04707 L 164.6223,155.68379 L 178.45042,155.68379 L 178.45042,158.04707 L 175.32542,158.04707 L 180.89183,175.95723 L 187.18089,155.68379 L 192.72777,155.68379 L 199.13402,176.28926 L 204.81761,158.04707 L 201.34105,158.04707 L 201.34105,155.68379 L 210.36449,155.68379 L 210.36449,158.04707 L 207.37621,158.04707 L 199.05589,184.84395 z"
1080+ id="text3683"
1081+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1082+ </g>
1083+ <g
1084+ id="g3949">
1085+ <path
1086+ d="M 376.75781,70.41095 L 376.75781,67.102356 L 381.98047,67.102356 L 381.98047,32.895325 L 376.75781,32.895325 L 376.75781,29.586731 L 389.52734,29.586731 L 414.16406,58.489075 L 414.16406,32.895325 L 408.96875,32.895325 L 408.96875,29.586731 L 423.24219,29.586731 L 423.24219,32.895325 L 418.01953,32.895325 L 418.01953,70.41095 L 410.85547,70.41095 L 385.83594,40.907043 L 385.83594,67.102356 L 391.03125,67.102356 L 391.03125,70.41095 L 376.75781,70.41095 z"
1087+ id="text3655"
1088+ style="font-size:56px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1089+ <path
1090+ d="M 750.00116,417.86914 C 753.4829,417.86914 756.07144,416.4017 757.76678,413.4668 C 759.46206,410.53191 760.30972,406.04754 760.30975,400.01367 C 760.30972,393.96161 759.46206,389.46813 757.76678,386.5332 C 756.07144,383.59834 753.4829,382.1309 750.00116,382.13086 C 746.5376,382.1309 743.95362,383.61202 742.24921,386.57422 C 740.54476,389.53649 739.69255,394.0163 739.69257,400.01367 C 739.69255,405.99285 740.54476,410.46355 742.24921,413.42578 C 743.95362,416.38802 746.5376,417.86914 750.00116,417.86914 L 750.00116,417.86914 z M 750.00116,421.17773 C 743.12875,421.17773 737.74203,419.30013 733.841,415.54492 C 729.93996,411.78972 727.98944,406.61264 727.98944,400.01367 C 727.98944,393.41474 729.94451,388.23311 733.85468,384.46875 C 737.76482,380.70447 743.14698,378.82231 750.00116,378.82227 C 756.87352,378.82231 762.26024,380.69991 766.16132,384.45508 C 770.06231,388.21032 772.01283,393.39651 772.01288,400.01367 C 772.01283,406.61264 770.05776,411.78972 766.14764,415.54492 C 762.23745,419.30013 756.8553,421.17773 750.00116,421.17773 L 750.00116,421.17773 z"
1091+ id="text3659"
1092+ style="font-size:56px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1093+ <path
1094+ d="M 383.93555,768.41687 L 383.93555,758.73718 L 387.4082,758.73718 C 387.93684,761.79969 389.18554,764.08745 391.1543,765.60046 C 393.12303,767.11349 395.84829,767.87 399.33008,767.87 C 402.15558,767.87 404.30662,767.33224 405.7832,766.25671 C 407.25974,765.1812 407.99802,763.60438 407.99805,761.52625 C 407.99802,759.88563 407.49672,758.60959 406.49414,757.69812 C 405.49151,756.78668 403.4225,755.93902 400.28711,755.15515 L 394.16211,753.65125 C 390.16991,752.63043 387.36262,751.21311 385.74023,749.39929 C 384.11783,747.58551 383.30664,745.00153 383.30664,741.64734 C 383.30664,737.6005 384.65104,734.45141 387.33984,732.20007 C 390.02864,729.94881 393.79751,728.82316 398.64648,728.82312 C 401.03448,728.82316 403.51821,729.02368 406.09766,729.42468 C 408.67705,729.82576 411.35218,730.42733 414.12305,731.22937 L 414.12305,740.25281 L 410.65039,740.25281 C 410.12171,737.44555 408.96416,735.39021 407.17773,734.08679 C 405.39125,732.78344 402.84828,732.13175 399.54883,732.13171 C 396.85089,732.13175 394.81379,732.60115 393.4375,733.53992 C 392.06119,734.47875 391.37304,735.87784 391.37305,737.73718 C 391.37304,739.43253 391.84699,740.72224 392.79492,741.60632 C 393.74282,742.49047 396.06704,743.40648 399.76758,744.35437 L 405.89258,745.85828 C 409.68421,746.80622 412.43226,748.28278 414.13672,750.28796 C 415.84111,752.29319 416.69332,755.05491 416.69336,758.57312 C 416.69332,762.69292 415.27145,765.82378 412.42773,767.9657 C 409.58395,770.10763 405.40036,771.17859 399.87695,771.17859 C 397.21548,771.17859 394.57225,770.95072 391.94727,770.495 C 389.32226,770.03927 386.65169,769.34656 383.93555,768.41687 L 383.93555,768.41687 z"
1095+ id="text3663"
1096+ style="font-size:56px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1097+ <path
1098+ d="M 66.186327,420.41211 L 59.131639,420.41211 L 49.889452,390.68945 L 40.647264,420.41211 L 33.592577,420.41211 L 21.944139,382.89648 L 17.979296,382.89648 L 17.979296,379.58789 L 37.338671,379.58789 L 37.338671,382.89648 L 32.963671,382.89648 L 40.756639,407.9707 L 49.561327,379.58789 L 57.326952,379.58789 L 66.295702,408.43555 L 74.252733,382.89648 L 69.385546,382.89648 L 69.385546,379.58789 L 82.018358,379.58789 L 82.018358,382.89648 L 77.834764,382.89648 L 66.186327,420.41211 z"
1099+ id="text3667"
1100+ style="font-size:56px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1101+ </g>
1102+ <g
1103+ id="g3961">
1104+ <path
1105+ d="M 70.921936,534.32635 L 70.921936,532.43573 L 73.906311,532.43573 L 73.906311,512.88885 L 70.921936,512.88885 L 70.921936,510.99823 L 78.218811,510.99823 L 92.296936,527.51385 L 92.296936,512.88885 L 89.328186,512.88885 L 89.328186,510.99823 L 97.484436,510.99823 L 97.484436,512.88885 L 94.500061,512.88885 L 94.500061,534.32635 L 90.406311,534.32635 L 76.109436,517.46698 L 76.109436,532.43573 L 79.078186,532.43573 L 79.078186,534.32635 L 70.921936,534.32635 z M 111.29694,534.32635 L 111.29694,532.43573 L 114.28131,532.43573 L 114.28131,512.88885 L 111.29694,512.88885 L 111.29694,510.99823 L 118.59381,510.99823 L 132.67194,527.51385 L 132.67194,512.88885 L 129.70319,512.88885 L 129.70319,510.99823 L 137.85944,510.99823 L 137.85944,512.88885 L 134.87506,512.88885 L 134.87506,534.32635 L 130.78131,534.32635 L 116.48444,517.46698 L 116.48444,532.43573 L 119.45319,532.43573 L 119.45319,534.32635 L 111.29694,534.32635 z M 153.06256,532.88885 C 155.05213,532.88886 156.53129,532.05032 157.50006,530.37323 C 158.46879,528.69615 158.95317,526.13365 158.95319,522.68573 C 158.95317,519.22741 158.46879,516.65971 157.50006,514.9826 C 156.53129,513.30554 155.05213,512.467 153.06256,512.46698 C 151.08338,512.467 149.60682,513.31336 148.63287,515.00604 C 147.65891,516.69877 147.17193,519.25866 147.17194,522.68573 C 147.17193,526.1024 147.65891,528.65709 148.63287,530.34979 C 149.60682,532.0425 151.08338,532.88886 153.06256,532.88885 L 153.06256,532.88885 z M 153.06256,534.77948 C 149.13547,534.77948 146.05735,533.70656 143.82819,531.56073 C 141.59902,529.4149 140.48443,526.45657 140.48444,522.68573 C 140.48443,518.91491 141.60162,515.95398 143.836,513.80292 C 146.07037,511.6519 149.14588,510.57638 153.06256,510.57635 C 156.98963,510.57638 160.06775,511.64929 162.29694,513.7951 C 164.52608,515.94096 165.64066,518.9045 165.64069,522.68573 C 165.64066,526.45657 164.52347,529.4149 162.28912,531.56073 C 160.05473,533.70656 156.97921,534.77948 153.06256,534.77948 L 153.06256,534.77948 z"
1106+ transform="matrix(0.3826834,-0.9238795,0.9238795,0.3826834,0,0)"
1107+ id="text3701"
1108+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1109+ <path
1110+ d="M 516.5737,532.94275 C 518.56327,532.94275 520.04243,532.10421 521.0112,530.42712 C 521.97993,528.75005 522.46431,526.18755 522.46432,522.73962 C 522.46431,519.28131 521.97993,516.7136 521.0112,515.0365 C 520.04243,513.35944 518.56327,512.5209 516.5737,512.52087 C 514.59452,512.5209 513.11796,513.36725 512.14401,515.05994 C 511.17005,516.75266 510.68307,519.31256 510.68307,522.73962 C 510.68307,526.1563 511.17005,528.71098 512.14401,530.40369 C 513.11796,532.0964 514.59452,532.94275 516.5737,532.94275 L 516.5737,532.94275 z M 516.5737,534.83337 C 512.64661,534.83337 509.56848,533.76046 507.33932,531.61462 C 505.11016,529.4688 503.99557,526.51047 503.99557,522.73962 C 503.99557,518.96881 505.11276,516.00787 507.34714,513.85681 C 509.58151,511.70579 512.65702,510.63027 516.5737,510.63025 C 520.50077,510.63027 523.57889,511.70319 525.80807,513.849 C 528.03722,515.99485 529.1518,518.95839 529.15182,522.73962 C 529.1518,526.51047 528.03461,529.4688 525.80026,531.61462 C 523.56587,533.76046 520.49035,534.83337 516.5737,534.83337 L 516.5737,534.83337 z M 543.05807,534.38025 L 543.05807,532.48962 L 546.04245,532.48962 L 546.04245,512.94275 L 543.05807,512.94275 L 543.05807,511.05212 L 550.35495,511.05212 L 564.43307,527.56775 L 564.43307,512.94275 L 561.46432,512.94275 L 561.46432,511.05212 L 569.62057,511.05212 L 569.62057,512.94275 L 566.6362,512.94275 L 566.6362,534.38025 L 562.54245,534.38025 L 548.24557,517.52087 L 548.24557,532.48962 L 551.21432,532.48962 L 551.21432,534.38025 L 543.05807,534.38025 z M 584.8237,532.94275 C 586.81327,532.94275 588.29243,532.10421 589.2612,530.42712 C 590.22993,528.75005 590.71431,526.18755 590.71432,522.73962 C 590.71431,519.28131 590.22993,516.7136 589.2612,515.0365 C 588.29243,513.35944 586.81327,512.5209 584.8237,512.52087 C 582.84452,512.5209 581.36796,513.36725 580.39401,515.05994 C 579.42005,516.75266 578.93307,519.31256 578.93307,522.73962 C 578.93307,526.1563 579.42005,528.71098 580.39401,530.40369 C 581.36796,532.0964 582.84452,532.94275 584.8237,532.94275 L 584.8237,532.94275 z M 584.8237,534.83337 C 580.89661,534.83337 577.81848,533.76046 575.58932,531.61462 C 573.36016,529.4688 572.24557,526.51047 572.24557,522.73962 C 572.24557,518.96881 573.36276,516.00787 575.59714,513.85681 C 577.83151,511.70579 580.90702,510.63027 584.8237,510.63025 C 588.75077,510.63027 591.82889,511.70319 594.05807,513.849 C 596.28722,515.99485 597.4018,518.95839 597.40182,522.73962 C 597.4018,526.51047 596.28461,529.4688 594.05026,531.61462 C 591.81587,533.76046 588.74035,534.83337 584.8237,534.83337 L 584.8237,534.83337 z"
1111+ transform="matrix(0.9238795,-0.3826834,0.3826834,0.9238795,0,0)"
1112+ id="text3705"
1113+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1114+ <path
1115+ d="M 822.79932,226.83607 C 824.78888,226.83608 826.26805,225.99754 827.23682,224.32045 C 828.20555,222.64337 828.68992,220.08087 828.68994,216.63295 C 828.68992,213.17463 828.20555,210.60693 827.23682,208.92982 C 826.26805,207.25276 824.78888,206.41422 822.79932,206.4142 C 820.82014,206.41422 819.34358,207.26058 818.36963,208.95326 C 817.39566,210.64599 816.90868,213.20588 816.90869,216.63295 C 816.90868,220.04962 817.39566,222.60431 818.36963,224.29701 C 819.34358,225.98972 820.82014,226.83608 822.79932,226.83607 L 822.79932,226.83607 z M 822.79932,228.7267 C 818.87222,228.7267 815.7941,227.65378 813.56494,225.50795 C 811.33577,223.36212 810.22119,220.40379 810.22119,216.63295 C 810.22119,212.86213 811.33838,209.9012 813.57275,207.75014 C 815.80712,205.59912 818.88264,204.5236 822.79932,204.52357 C 826.72638,204.5236 829.8045,205.59651 832.03369,207.74232 C 834.26283,209.88818 835.37741,212.85172 835.37744,216.63295 C 835.37741,220.40379 834.26023,223.36212 832.02588,225.50795 C 829.79148,227.65378 826.71597,228.7267 822.79932,228.7267 L 822.79932,228.7267 z M 850.34619,227.14857 L 850.34619,221.61732 L 852.33057,221.61732 C 852.63264,223.36733 853.34619,224.67462 854.47119,225.5392 C 855.59618,226.40379 857.15347,226.83608 859.14307,226.83607 C 860.75764,226.83608 861.9868,226.52878 862.83057,225.9142 C 863.6743,225.29962 864.09618,224.39858 864.09619,223.21107 C 864.09618,222.27358 863.80972,221.54441 863.23682,221.02357 C 862.66388,220.50275 861.48159,220.01837 859.68994,219.57045 L 856.18994,218.71107 C 853.90869,218.12775 852.30452,217.31786 851.37744,216.28139 C 850.45036,215.24494 849.98681,213.76838 849.98682,211.8517 C 849.98681,209.53922 850.75504,207.73974 852.2915,206.45326 C 853.82796,205.16683 855.9816,204.5236 858.75244,204.52357 C 860.11701,204.5236 861.53628,204.63818 863.01025,204.86732 C 864.4842,205.09651 866.01284,205.44026 867.59619,205.89857 L 867.59619,211.05482 L 865.61182,211.05482 C 865.30972,209.45068 864.64826,208.2762 863.62744,207.53139 C 862.60659,206.78662 861.15347,206.41422 859.26807,206.4142 C 857.72639,206.41422 856.56233,206.68245 855.77588,207.21889 C 854.98941,207.75537 854.59618,208.55484 854.59619,209.61732 C 854.59618,210.58609 854.86702,211.32307 855.40869,211.82826 C 855.95035,212.33349 857.27847,212.85692 859.39307,213.39857 L 862.89307,214.25795 C 865.05972,214.79963 866.63003,215.64338 867.604,216.7892 C 868.57794,217.93504 869.06492,219.51317 869.06494,221.52357 C 869.06492,223.87775 868.25242,225.66681 866.62744,226.89076 C 865.00242,228.11472 862.6118,228.7267 859.45557,228.7267 C 857.93472,228.7267 856.42431,228.59649 854.92432,228.33607 C 853.42431,228.07566 851.89827,227.67983 850.34619,227.14857 L 850.34619,227.14857 z M 884.92432,226.83607 C 886.91388,226.83608 888.39305,225.99754 889.36182,224.32045 C 890.33055,222.64337 890.81492,220.08087 890.81494,216.63295 C 890.81492,213.17463 890.33055,210.60693 889.36182,208.92982 C 888.39305,207.25276 886.91388,206.41422 884.92432,206.4142 C 882.94514,206.41422 881.46858,207.26058 880.49463,208.95326 C 879.52066,210.64599 879.03368,213.20588 879.03369,216.63295 C 879.03368,220.04962 879.52066,222.60431 880.49463,224.29701 C 881.46858,225.98972 882.94514,226.83608 884.92432,226.83607 L 884.92432,226.83607 z M 884.92432,228.7267 C 880.99722,228.7267 877.9191,227.65378 875.68994,225.50795 C 873.46077,223.36212 872.34619,220.40379 872.34619,216.63295 C 872.34619,212.86213 873.46338,209.9012 875.69775,207.75014 C 877.93212,205.59912 881.00764,204.5236 884.92432,204.52357 C 888.85138,204.5236 891.9295,205.59651 894.15869,207.74232 C 896.38783,209.88818 897.50241,212.85172 897.50244,216.63295 C 897.50241,220.40379 896.38523,223.36212 894.15088,225.50795 C 891.91648,227.65378 888.84097,228.7267 884.92432,228.7267 L 884.92432,228.7267 z"
1116+ transform="matrix(0.9238795,0.3826834,-0.3826834,0.9238795,0,0)"
1117+ id="text3709"
1118+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1119+ <path
1120+ d="M 810.52289,-205.01591 L 810.52289,-210.54716 L 812.50726,-210.54716 C 812.80934,-208.79716 813.52288,-207.48987 814.64789,-206.62529 C 815.77288,-205.7607 817.33017,-205.32841 819.31976,-205.32841 C 820.93433,-205.32841 822.1635,-205.6357 823.00726,-206.25029 C 823.851,-206.86487 824.27287,-207.76591 824.27289,-208.95341 C 824.27287,-209.89091 823.98641,-210.62007 823.41351,-211.14091 C 822.84058,-211.66174 821.65829,-212.14611 819.86664,-212.59404 L 816.36664,-213.45341 C 814.08538,-214.03674 812.48122,-214.84663 811.55414,-215.8831 C 810.62705,-216.91955 810.16351,-218.39611 810.16351,-220.31279 C 810.16351,-222.62527 810.93174,-224.42475 812.4682,-225.71123 C 814.00465,-226.99766 816.1583,-227.64089 818.92914,-227.64091 C 820.29371,-227.64089 821.71298,-227.52631 823.18695,-227.29716 C 824.66089,-227.06798 826.18954,-226.72423 827.77289,-226.26591 L 827.77289,-221.10966 L 825.78851,-221.10966 C 825.48641,-222.71381 824.82495,-223.88829 823.80414,-224.6331 C 822.78329,-225.37787 821.33017,-225.75027 819.44476,-225.75029 C 817.90309,-225.75027 816.73903,-225.48204 815.95258,-224.9456 C 815.16611,-224.40912 814.77288,-223.60965 814.77289,-222.54716 C 814.77288,-221.5784 815.04371,-220.84142 815.58539,-220.33623 C 816.12705,-219.831 817.45517,-219.30757 819.56976,-218.76591 L 823.06976,-217.90654 C 825.23641,-217.36486 826.80672,-216.52111 827.7807,-215.37529 C 828.75464,-214.22945 829.24162,-212.65132 829.24164,-210.64091 C 829.24162,-208.28674 828.42912,-206.49768 826.80414,-205.27373 C 825.17912,-204.04977 822.7885,-203.43779 819.63226,-203.43779 C 818.11142,-203.43779 816.601,-203.568 815.10101,-203.82841 C 813.60101,-204.08883 812.07497,-204.48466 810.52289,-205.01591 L 810.52289,-205.01591 z M 844.77289,-205.01591 L 844.77289,-210.54716 L 846.75726,-210.54716 C 847.05934,-208.79716 847.77288,-207.48987 848.89789,-206.62529 C 850.02288,-205.7607 851.58017,-205.32841 853.56976,-205.32841 C 855.18433,-205.32841 856.4135,-205.6357 857.25726,-206.25029 C 858.101,-206.86487 858.52287,-207.76591 858.52289,-208.95341 C 858.52287,-209.89091 858.23641,-210.62007 857.66351,-211.14091 C 857.09058,-211.66174 855.90829,-212.14611 854.11664,-212.59404 L 850.61664,-213.45341 C 848.33538,-214.03674 846.73122,-214.84663 845.80414,-215.8831 C 844.87705,-216.91955 844.41351,-218.39611 844.41351,-220.31279 C 844.41351,-222.62527 845.18174,-224.42475 846.7182,-225.71123 C 848.25465,-226.99766 850.4083,-227.64089 853.17914,-227.64091 C 854.54371,-227.64089 855.96298,-227.52631 857.43695,-227.29716 C 858.91089,-227.06798 860.43954,-226.72423 862.02289,-226.26591 L 862.02289,-221.10966 L 860.03851,-221.10966 C 859.73641,-222.71381 859.07495,-223.88829 858.05414,-224.6331 C 857.03329,-225.37787 855.58017,-225.75027 853.69476,-225.75029 C 852.15309,-225.75027 850.98903,-225.48204 850.20258,-224.9456 C 849.41611,-224.40912 849.02288,-223.60965 849.02289,-222.54716 C 849.02288,-221.5784 849.29371,-220.84142 849.83539,-220.33623 C 850.37705,-219.831 851.70517,-219.30757 853.81976,-218.76591 L 857.31976,-217.90654 C 859.48641,-217.36486 861.05672,-216.52111 862.0307,-215.37529 C 863.00464,-214.22945 863.49162,-212.65132 863.49164,-210.64091 C 863.49162,-208.28674 862.67912,-206.49768 861.05414,-205.27373 C 859.42912,-204.04977 857.0385,-203.43779 853.88226,-203.43779 C 852.36142,-203.43779 850.851,-203.568 849.35101,-203.82841 C 847.85101,-204.08883 846.32497,-204.48466 844.77289,-205.01591 L 844.77289,-205.01591 z M 879.35101,-205.32841 C 881.34058,-205.32841 882.81975,-206.16695 883.78851,-207.84404 C 884.75724,-209.52112 885.24162,-212.08362 885.24164,-215.53154 C 885.24162,-218.98986 884.75724,-221.55756 883.78851,-223.23466 C 882.81975,-224.91173 881.34058,-225.75027 879.35101,-225.75029 C 877.37183,-225.75027 875.89527,-224.90391 874.92133,-223.21123 C 873.94736,-221.5185 873.46038,-218.95861 873.46039,-215.53154 C 873.46038,-212.11487 873.94736,-209.56018 874.92133,-207.86748 C 875.89527,-206.17477 877.37183,-205.32841 879.35101,-205.32841 L 879.35101,-205.32841 z M 879.35101,-203.43779 C 875.42392,-203.43779 872.3458,-204.51071 870.11664,-206.65654 C 867.88747,-208.80237 866.77289,-211.7607 866.77289,-215.53154 C 866.77289,-219.30236 867.89007,-222.26329 870.12445,-224.41435 C 872.35882,-226.56537 875.43434,-227.64089 879.35101,-227.64091 C 883.27808,-227.64089 886.3562,-226.56798 888.58539,-224.42216 C 890.81453,-222.27631 891.92911,-219.31277 891.92914,-215.53154 C 891.92911,-211.7607 890.81193,-208.80237 888.57758,-206.65654 C 886.34318,-204.51071 883.26766,-203.43779 879.35101,-203.43779 L 879.35101,-203.43779 z"
1121+ transform="matrix(0.3826834,0.9238795,-0.9238795,0.3826834,0,0)"
1122+ id="text3713"
1123+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1124+ <path
1125+ d="M -595.03589,533.53064 L -595.03589,527.99939 L -593.05151,527.99939 C -592.74944,529.74939 -592.03589,531.05668 -590.91089,531.92126 C -589.7859,532.78585 -588.22861,533.21814 -586.23901,533.21814 C -584.62444,533.21814 -583.39528,532.91085 -582.55151,532.29626 C -581.70778,531.68168 -581.2859,530.78064 -581.28589,529.59314 C -581.2859,528.65565 -581.57236,527.92648 -582.14526,527.40564 C -582.7182,526.88481 -583.90049,526.40044 -585.69214,525.95251 L -589.19214,525.09314 C -591.47339,524.50982 -593.07756,523.69992 -594.00464,522.66345 C -594.93172,521.62701 -595.39527,520.15045 -595.39526,518.23376 C -595.39527,515.92128 -594.62704,514.12181 -593.09058,512.83533 C -591.55412,511.54889 -589.40048,510.90566 -586.62964,510.90564 C -585.26507,510.90566 -583.8458,511.02025 -582.37183,511.24939 C -580.89788,511.47858 -579.36924,511.82233 -577.78589,512.28064 L -577.78589,517.43689 L -579.77026,517.43689 C -580.07236,515.83274 -580.73382,514.65826 -581.75464,513.91345 C -582.77549,513.16868 -584.22861,512.79629 -586.11401,512.79626 C -587.65569,512.79629 -588.81975,513.06452 -589.6062,513.60095 C -590.39267,514.13743 -590.7859,514.93691 -590.78589,515.99939 C -590.7859,516.96816 -590.51506,517.70514 -589.97339,518.21033 C -589.43173,518.71555 -588.10361,519.23899 -585.98901,519.78064 L -582.48901,520.64001 C -580.32236,521.18169 -578.75205,522.02544 -577.77808,523.17126 C -576.80414,524.31711 -576.31716,525.89523 -576.31714,527.90564 C -576.31716,530.25981 -577.12966,532.04887 -578.75464,533.27283 C -580.37966,534.49679 -582.77028,535.10876 -585.92651,535.10876 C -587.44736,535.10876 -588.95777,534.97856 -590.45776,534.71814 C -591.95777,534.45772 -593.48381,534.06189 -595.03589,533.53064 L -595.03589,533.53064 z M -560.78589,533.53064 L -560.78589,527.99939 L -558.80151,527.99939 C -558.49944,529.74939 -557.78589,531.05668 -556.66089,531.92126 C -555.5359,532.78585 -553.97861,533.21814 -551.98901,533.21814 C -550.37444,533.21814 -549.14528,532.91085 -548.30151,532.29626 C -547.45778,531.68168 -547.0359,530.78064 -547.03589,529.59314 C -547.0359,528.65565 -547.32236,527.92648 -547.89526,527.40564 C -548.4682,526.88481 -549.65049,526.40044 -551.44214,525.95251 L -554.94214,525.09314 C -557.22339,524.50982 -558.82756,523.69992 -559.75464,522.66345 C -560.68172,521.62701 -561.14527,520.15045 -561.14526,518.23376 C -561.14527,515.92128 -560.37704,514.12181 -558.84058,512.83533 C -557.30412,511.54889 -555.15048,510.90566 -552.37964,510.90564 C -551.01507,510.90566 -549.5958,511.02025 -548.12183,511.24939 C -546.64788,511.47858 -545.11924,511.82233 -543.53589,512.28064 L -543.53589,517.43689 L -545.52026,517.43689 C -545.82236,515.83274 -546.48382,514.65826 -547.50464,513.91345 C -548.52549,513.16868 -549.97861,512.79629 -551.86401,512.79626 C -553.40569,512.79629 -554.56975,513.06452 -555.3562,513.60095 C -556.14267,514.13743 -556.5359,514.93691 -556.53589,515.99939 C -556.5359,516.96816 -556.26506,517.70514 -555.72339,518.21033 C -555.18173,518.71555 -553.85361,519.23899 -551.73901,519.78064 L -548.23901,520.64001 C -546.07236,521.18169 -544.50205,522.02544 -543.52808,523.17126 C -542.55414,524.31711 -542.06716,525.89523 -542.06714,527.90564 C -542.06716,530.25981 -542.87966,532.04887 -544.50464,533.27283 C -546.12966,534.49679 -548.52028,535.10876 -551.67651,535.10876 C -553.19736,535.10876 -554.70777,534.97856 -556.20776,534.71814 C -557.70777,534.45772 -559.23381,534.06189 -560.78589,533.53064 L -560.78589,533.53064 z M -512.86401,534.65564 L -516.89526,534.65564 L -522.17651,517.67126 L -527.45776,534.65564 L -531.48901,534.65564 L -538.14526,513.21814 L -540.41089,513.21814 L -540.41089,511.32751 L -529.34839,511.32751 L -529.34839,513.21814 L -531.84839,513.21814 L -527.39526,527.54626 L -522.36401,511.32751 L -517.92651,511.32751 L -512.80151,527.81189 L -508.25464,513.21814 L -511.03589,513.21814 L -511.03589,511.32751 L -503.81714,511.32751 L -503.81714,513.21814 L -506.20776,513.21814 L -512.86401,534.65564 z"
1126+ transform="matrix(0.3826834,-0.9238795,0.9238795,0.3826834,0,0)"
1127+ id="text3717"
1128+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1129+ <path
1130+ d="M -150.12714,534.41028 L -154.15839,534.41028 L -159.43964,517.4259 L -164.72089,534.41028 L -168.75214,534.41028 L -175.40839,512.97278 L -177.67401,512.97278 L -177.67401,511.08215 L -166.61151,511.08215 L -166.61151,512.97278 L -169.11151,512.97278 L -164.65839,527.3009 L -159.62714,511.08215 L -155.18964,511.08215 L -150.06464,527.56653 L -145.51776,512.97278 L -148.29901,512.97278 L -148.29901,511.08215 L -141.08026,511.08215 L -141.08026,512.97278 L -143.47089,512.97278 L -150.12714,534.41028 z M -127.86151,533.28528 L -127.86151,527.75403 L -125.87714,527.75403 C -125.57506,529.50403 -124.86152,530.81132 -123.73651,531.6759 C -122.61152,532.54049 -121.05423,532.97278 -119.06464,532.97278 C -117.45007,532.97278 -116.2209,532.66549 -115.37714,532.0509 C -114.5334,531.43632 -114.11153,530.53528 -114.11151,529.34778 C -114.11153,528.41028 -114.39799,527.68112 -114.97089,527.16028 C -115.54382,526.63945 -116.72611,526.15508 -118.51776,525.70715 L -122.01776,524.84778 C -124.29902,524.26446 -125.90318,523.45456 -126.83026,522.41809 C -127.75735,521.38165 -128.22089,519.90508 -128.22089,517.9884 C -128.22089,515.67592 -127.45266,513.87644 -125.9162,512.58997 C -124.37975,511.30353 -122.2261,510.6603 -119.45526,510.66028 C -118.09069,510.6603 -116.67142,510.77489 -115.19745,511.00403 C -113.72351,511.23322 -112.19486,511.57697 -110.61151,512.03528 L -110.61151,517.19153 L -112.59589,517.19153 C -112.89799,515.58738 -113.55944,514.4129 -114.58026,513.66809 C -115.60111,512.92332 -117.05423,512.55093 -118.93964,512.5509 C -120.48131,512.55093 -121.64537,512.81915 -122.43182,513.35559 C -123.21829,513.89207 -123.61152,514.69155 -123.61151,515.75403 C -123.61152,516.7228 -123.34068,517.45977 -122.79901,517.96497 C -122.25735,518.47019 -120.92923,518.99363 -118.81464,519.53528 L -115.31464,520.39465 C -113.14799,520.93633 -111.57768,521.78008 -110.6037,522.9259 C -109.62976,524.07175 -109.14278,525.64987 -109.14276,527.66028 C -109.14278,530.01445 -109.95528,531.80351 -111.58026,533.02747 C -113.20528,534.25142 -115.5959,534.8634 -118.75214,534.8634 C -120.27298,534.8634 -121.78339,534.73319 -123.28339,534.47278 C -124.78339,534.21236 -126.30943,533.81653 -127.86151,533.28528 L -127.86151,533.28528 z M -79.939636,534.41028 L -83.970886,534.41028 L -89.252136,517.4259 L -94.533386,534.41028 L -98.564636,534.41028 L -105.22089,512.97278 L -107.48651,512.97278 L -107.48651,511.08215 L -96.424011,511.08215 L -96.424011,512.97278 L -98.924011,512.97278 L -94.470886,527.3009 L -89.439636,511.08215 L -85.002136,511.08215 L -79.877136,527.56653 L -75.330261,512.97278 L -78.111511,512.97278 L -78.111511,511.08215 L -70.892761,511.08215 L -70.892761,512.97278 L -73.283386,512.97278 L -79.939636,534.41028 z"
1131+ transform="matrix(0.9238795,-0.3826834,0.3826834,0.9238795,0,0)"
1132+ id="text3721"
1133+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1134+ <path
1135+ d="M 149.90634,228.33632 L 145.87509,228.33632 L 140.59384,211.35194 L 135.31259,228.33632 L 131.28134,228.33632 L 124.62509,206.89882 L 122.35947,206.89882 L 122.35947,205.00819 L 133.42197,205.00819 L 133.42197,206.89882 L 130.92197,206.89882 L 135.37509,221.22694 L 140.40634,205.00819 L 144.84384,205.00819 L 149.96884,221.49257 L 154.51572,206.89882 L 151.73447,206.89882 L 151.73447,205.00819 L 158.95322,205.00819 L 158.95322,206.89882 L 156.56259,206.89882 L 149.90634,228.33632 z M 171.10947,228.33632 L 171.10947,226.44569 L 174.09384,226.44569 L 174.09384,206.89882 L 171.10947,206.89882 L 171.10947,205.00819 L 178.40634,205.00819 L 192.48447,221.52382 L 192.48447,206.89882 L 189.51572,206.89882 L 189.51572,205.00819 L 197.67197,205.00819 L 197.67197,206.89882 L 194.68759,206.89882 L 194.68759,228.33632 L 190.59384,228.33632 L 176.29697,211.47694 L 176.29697,226.44569 L 179.26572,226.44569 L 179.26572,228.33632 L 171.10947,228.33632 z M 226.21884,228.33632 L 222.18759,228.33632 L 216.90634,211.35194 L 211.62509,228.33632 L 207.59384,228.33632 L 200.93759,206.89882 L 198.67197,206.89882 L 198.67197,205.00819 L 209.73447,205.00819 L 209.73447,206.89882 L 207.23447,206.89882 L 211.68759,221.22694 L 216.71884,205.00819 L 221.15634,205.00819 L 226.28134,221.49257 L 230.82822,206.89882 L 228.04697,206.89882 L 228.04697,205.00819 L 235.26572,205.00819 L 235.26572,206.89882 L 232.87509,206.89882 L 226.21884,228.33632 z"
1136+ transform="matrix(0.9238795,0.3826834,-0.3826834,0.9238795,0,0)"
1137+ id="text3725"
1138+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1139+ <path
1140+ d="M 130.64632,-204.84834 L 130.64632,-206.73897 L 133.63069,-206.73897 L 133.63069,-226.28584 L 130.64632,-226.28584 L 130.64632,-228.17647 L 137.94319,-228.17647 L 152.02132,-211.66084 L 152.02132,-226.28584 L 149.05257,-226.28584 L 149.05257,-228.17647 L 157.20882,-228.17647 L 157.20882,-226.28584 L 154.22444,-226.28584 L 154.22444,-204.84834 L 150.13069,-204.84834 L 135.83382,-221.70772 L 135.83382,-206.73897 L 138.80257,-206.73897 L 138.80257,-204.84834 L 130.64632,-204.84834 z M 171.02132,-204.84834 L 171.02132,-206.73897 L 174.00569,-206.73897 L 174.00569,-226.28584 L 171.02132,-226.28584 L 171.02132,-228.17647 L 178.31819,-228.17647 L 192.39632,-211.66084 L 192.39632,-226.28584 L 189.42757,-226.28584 L 189.42757,-228.17647 L 197.58382,-228.17647 L 197.58382,-226.28584 L 194.59944,-226.28584 L 194.59944,-204.84834 L 190.50569,-204.84834 L 176.20882,-221.70772 L 176.20882,-206.73897 L 179.17757,-206.73897 L 179.17757,-204.84834 L 171.02132,-204.84834 z M 226.13069,-204.84834 L 222.09944,-204.84834 L 216.81819,-221.83272 L 211.53694,-204.84834 L 207.50569,-204.84834 L 200.84944,-226.28584 L 198.58382,-226.28584 L 198.58382,-228.17647 L 209.64632,-228.17647 L 209.64632,-226.28584 L 207.14632,-226.28584 L 211.59944,-211.95772 L 216.63069,-228.17647 L 221.06819,-228.17647 L 226.19319,-211.69209 L 230.74007,-226.28584 L 227.95882,-226.28584 L 227.95882,-228.17647 L 235.17757,-228.17647 L 235.17757,-226.28584 L 232.78694,-226.28584 L 226.13069,-204.84834 z"
1141+ transform="matrix(0.3826834,0.9238795,-0.9238795,0.3826834,0,0)"
1142+ id="text3729"
1143+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1144+ </g>
1145+ <g
1146+ id="g3971">
1147+ <path
1148+ d="M -39.29726,479.22076 L -39.29726,477.8028 L -37.058979,477.8028 L -37.058979,463.14264 L -39.29726,463.14264 L -39.29726,461.72467 L -33.824604,461.72467 L -23.26601,474.11139 L -23.26601,463.14264 L -25.492573,463.14264 L -25.492573,461.72467 L -19.375385,461.72467 L -19.375385,463.14264 L -21.613667,463.14264 L -21.613667,479.22076 L -24.683979,479.22076 L -35.406635,466.57623 L -35.406635,477.8028 L -33.180073,477.8028 L -33.180073,479.22076 L -39.29726,479.22076 z M -17.570698,479.22076 L -17.570698,477.8028 L -10.42226,468.13483 L -15.801167,468.13483 L -15.801167,470.26764 L -17.195698,470.26764 L -17.195698,466.76373 L -5.5941353,466.76373 L -5.5941353,468.15826 L -12.754292,477.82623 L -6.9886665,477.82623 L -6.9886665,475.57623 L -5.5941353,475.57623 L -5.5941353,479.22076 L -17.570698,479.22076 z M 5.6675835,478.14264 C 7.159759,478.14264 8.2691329,477.51373 8.9957085,476.25592 C 9.7222565,474.99811 10.085537,473.07624 10.085552,470.4903 C 10.085537,467.89656 9.7222565,465.97078 8.9957085,464.71295 C 8.2691329,463.45515 7.159759,462.82625 5.6675835,462.82623 C 4.1831995,462.82625 3.0757787,463.46101 2.3453178,464.73053 C 1.6148427,466.00007 1.2496087,467.91999 1.2496147,470.4903 C 1.2496087,473.0528 1.6148427,474.96882 2.3453178,476.23834 C 3.0757787,477.50788 4.1831995,478.14264 5.6675835,478.14264 L 5.6675835,478.14264 z M 5.6675835,479.56061 C 2.7222635,479.56061 0.41367203,478.75592 -1.2581978,477.14655 C -2.9300746,475.53717 -3.7660113,473.31843 -3.7660103,470.4903 C -3.7660113,467.66218 -2.9281215,465.44148 -1.2523384,463.82819 C 0.42343764,462.21492 2.730076,461.40828 5.6675835,461.40826 C 8.6128826,461.40828 10.921474,462.21297 12.593365,463.82233 C 14.265221,465.43172 15.101157,467.65437 15.101177,470.4903 C 15.101157,473.31843 14.263268,475.53717 12.587505,477.14655 C 10.911708,478.75592 8.6050701,479.56061 5.6675835,479.56061 L 5.6675835,479.56061 z"
1149+ transform="matrix(0.1950903,-0.9807853,0.9807853,0.1950903,0,0)"
1150+ id="text3815"
1151+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1152+ <path
1153+ d="M 164.54842,564.11603 L 164.54842,562.69806 L 166.7867,562.69806 L 166.7867,548.0379 L 164.54842,548.0379 L 164.54842,546.61993 L 170.02107,546.61993 L 180.57967,559.00665 L 180.57967,548.0379 L 178.3531,548.0379 L 178.3531,546.61993 L 184.47029,546.61993 L 184.47029,548.0379 L 182.23201,548.0379 L 182.23201,564.11603 L 179.1617,564.11603 L 168.43904,551.4715 L 168.43904,562.69806 L 170.6656,562.69806 L 170.6656,564.11603 L 164.54842,564.11603 z M 195.87263,563.0379 C 197.36481,563.0379 198.47418,562.409 199.20076,561.15118 C 199.92731,559.89338 200.29059,557.9715 200.2906,555.38556 C 200.29059,552.79182 199.92731,550.86604 199.20076,549.60822 C 198.47418,548.35042 197.36481,547.72151 195.87263,547.7215 C 194.38825,547.72151 193.28083,548.35628 192.55037,549.62579 C 191.81989,550.89534 191.45466,552.81526 191.45467,555.38556 C 191.45466,557.94807 191.81989,559.86408 192.55037,561.13361 C 193.28083,562.40314 194.38825,563.0379 195.87263,563.0379 L 195.87263,563.0379 z M 195.87263,564.45587 C 192.92731,564.45587 190.61872,563.65118 188.94685,562.04181 C 187.27498,560.43244 186.43904,558.21369 186.43904,555.38556 C 186.43904,552.55745 187.27693,550.33674 188.95271,548.72345 C 190.62849,547.11019 192.93513,546.30355 195.87263,546.30353 C 198.81793,546.30355 201.12653,547.10823 202.79842,548.71759 C 204.47027,550.32698 205.30621,552.54963 205.30623,555.38556 C 205.30621,558.21369 204.46832,560.43244 202.79256,562.04181 C 201.11676,563.65118 198.81012,564.45587 195.87263,564.45587 L 195.87263,564.45587 z M 207.18123,564.11603 L 207.18123,562.69806 L 214.32967,553.03009 L 208.95076,553.03009 L 208.95076,555.1629 L 207.55623,555.1629 L 207.55623,551.659 L 219.15779,551.659 L 219.15779,553.05353 L 211.99763,562.7215 L 217.76326,562.7215 L 217.76326,560.4715 L 219.15779,560.4715 L 219.15779,564.11603 L 207.18123,564.11603 z M 221.03279,564.11603 L 221.03279,562.69806 L 223.27107,562.69806 L 223.27107,548.0379 L 221.03279,548.0379 L 221.03279,546.61993 L 226.50545,546.61993 L 237.06404,559.00665 L 237.06404,548.0379 L 234.83748,548.0379 L 234.83748,546.61993 L 240.95467,546.61993 L 240.95467,548.0379 L 238.71638,548.0379 L 238.71638,564.11603 L 235.64607,564.11603 L 224.92342,551.4715 L 224.92342,562.69806 L 227.14998,562.69806 L 227.14998,564.11603 L 221.03279,564.11603 z"
1154+ transform="matrix(0.5555702,-0.8314696,0.8314696,0.5555702,0,0)"
1155+ id="text3819"
1156+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1157+ <path
1158+ d="M 385.28525,563.69904 L 385.28525,562.28107 L 387.52353,562.28107 L 387.52353,547.62091 L 385.28525,547.62091 L 385.28525,546.20294 L 390.7579,546.20294 L 401.3165,558.58966 L 401.3165,547.62091 L 399.08994,547.62091 L 399.08994,546.20294 L 405.20712,546.20294 L 405.20712,547.62091 L 402.96884,547.62091 L 402.96884,563.69904 L 399.89853,563.69904 L 389.17587,551.0545 L 389.17587,562.28107 L 391.40244,562.28107 L 391.40244,563.69904 L 385.28525,563.69904 z M 416.60947,562.62091 C 418.10164,562.62091 419.21102,561.99201 419.93759,560.73419 C 420.66414,559.47638 421.02742,557.55451 421.02744,554.96857 C 421.02742,552.37483 420.66414,550.44905 419.93759,549.19122 C 419.21102,547.93343 418.10164,547.30452 416.60947,547.3045 C 415.12508,547.30452 414.01766,547.93929 413.2872,549.2088 C 412.55673,550.47835 412.19149,552.39827 412.1915,554.96857 C 412.19149,557.53107 412.55673,559.44709 413.2872,560.71661 C 414.01766,561.98615 415.12508,562.62091 416.60947,562.62091 L 416.60947,562.62091 z M 416.60947,564.03888 C 413.66415,564.03888 411.35556,563.23419 409.68369,561.62482 C 408.01181,560.01545 407.17587,557.7967 407.17587,554.96857 C 407.17587,552.14045 408.01376,549.91975 409.68954,548.30646 C 411.36532,546.69319 413.67196,545.88655 416.60947,545.88654 C 419.55477,545.88655 421.86336,546.69124 423.53525,548.3006 C 425.2071,549.90999 426.04304,552.13264 426.04306,554.96857 C 426.04304,557.7967 425.20515,560.01545 423.52939,561.62482 C 421.85359,563.23419 419.54695,564.03888 416.60947,564.03888 L 416.60947,564.03888 z M 427.91806,563.69904 L 427.91806,562.28107 L 435.0665,552.6131 L 429.68759,552.6131 L 429.68759,554.74591 L 428.29306,554.74591 L 428.29306,551.242 L 439.89462,551.242 L 439.89462,552.63654 L 432.73447,562.3045 L 438.50009,562.3045 L 438.50009,560.0545 L 439.89462,560.0545 L 439.89462,563.69904 L 427.91806,563.69904 z M 451.15634,562.62091 C 452.64852,562.62091 453.75789,561.99201 454.48447,560.73419 C 455.21101,559.47638 455.5743,557.55451 455.57431,554.96857 C 455.5743,552.37483 455.21101,550.44905 454.48447,549.19122 C 453.75789,547.93343 452.64852,547.30452 451.15634,547.3045 C 449.67196,547.30452 448.56454,547.93929 447.83408,549.2088 C 447.1036,550.47835 446.73837,552.39827 446.73837,554.96857 C 446.73837,557.53107 447.1036,559.44709 447.83408,560.71661 C 448.56454,561.98615 449.67196,562.62091 451.15634,562.62091 L 451.15634,562.62091 z M 451.15634,564.03888 C 448.21102,564.03888 445.90243,563.23419 444.23056,561.62482 C 442.55868,560.01545 441.72275,557.7967 441.72275,554.96857 C 441.72275,552.14045 442.56064,549.91975 444.23642,548.30646 C 445.9122,546.69319 448.21883,545.88655 451.15634,545.88654 C 454.10164,545.88655 456.41023,546.69124 458.08212,548.3006 C 459.75398,549.90999 460.58992,552.13264 460.58994,554.96857 C 460.58992,557.7967 459.75203,560.01545 458.07626,561.62482 C 456.40047,563.23419 454.09383,564.03888 451.15634,564.03888 L 451.15634,564.03888 z"
1159+ transform="matrix(0.8314696,-0.5555702,0.5555702,0.8314696,0,0)"
1160+ id="text3823"
1161+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1162+ <path
1163+ d="M 754.82623,321.96481 C 756.31841,321.96481 757.42778,321.33591 758.15436,320.07809 C 758.88091,318.82029 759.24419,316.89841 759.2442,314.31247 C 759.24419,311.71873 758.88091,309.79295 758.15436,308.53513 C 757.42778,307.27733 756.31841,306.64842 754.82623,306.64841 C 753.34185,306.64842 752.23443,307.28319 751.50397,308.5527 C 750.77349,309.82225 750.40826,311.74217 750.40826,314.31247 C 750.40826,316.87498 750.77349,318.79099 751.50397,320.06052 C 752.23443,321.33005 753.34185,321.96481 754.82623,321.96481 L 754.82623,321.96481 z M 754.82623,323.38278 C 751.88091,323.38278 749.57232,322.57809 747.90045,320.96872 C 746.22857,319.35935 745.39264,317.1406 745.39264,314.31247 C 745.39264,311.48436 746.23053,309.26366 747.90631,307.65036 C 749.58209,306.0371 751.88873,305.23046 754.82623,305.23044 C 757.77153,305.23046 760.08012,306.03514 761.75201,307.6445 C 763.42387,309.25389 764.25981,311.47654 764.25983,314.31247 C 764.25981,317.1406 763.42192,319.35935 761.74615,320.96872 C 760.07036,322.57809 757.76372,323.38278 754.82623,323.38278 L 754.82623,323.38278 z M 766.13483,323.04294 L 766.13483,321.62497 L 773.28326,311.957 L 767.90436,311.957 L 767.90436,314.08981 L 766.50983,314.08981 L 766.50983,310.58591 L 778.11139,310.58591 L 778.11139,311.98044 L 770.95123,321.64841 L 776.71686,321.64841 L 776.71686,319.39841 L 778.11139,319.39841 L 778.11139,323.04294 L 766.13483,323.04294 z M 780.78326,322.19919 L 780.78326,318.05075 L 782.27155,318.05075 C 782.4981,319.36325 783.03326,320.34372 783.87701,320.99216 C 784.72076,321.6406 785.88873,321.96481 787.38092,321.96481 C 788.59185,321.96481 789.51372,321.73435 790.14655,321.27341 C 790.77935,320.81247 791.09575,320.13669 791.09576,319.24606 C 791.09575,318.54294 790.88091,317.99607 790.45123,317.60544 C 790.02153,317.21482 789.13482,316.85154 787.79108,316.51559 L 785.16608,315.87106 C 783.45513,315.43357 782.25201,314.82615 781.5567,314.0488 C 780.86139,313.27146 780.51373,312.16404 780.51373,310.72653 C 780.51373,308.99217 781.0899,307.64256 782.24225,306.6777 C 783.39459,305.71288 785.00982,305.23046 787.08795,305.23044 C 788.11138,305.23046 789.17583,305.31639 790.28131,305.48825 C 791.38677,305.66014 792.53325,305.91796 793.72076,306.26169 L 793.72076,310.12888 L 792.23248,310.12888 C 792.00591,308.92576 791.50981,308.04491 790.7442,307.4863 C 789.97857,306.92772 788.88872,306.64842 787.47467,306.64841 C 786.31841,306.64842 785.44537,306.8496 784.85553,307.25192 C 784.26568,307.65428 783.97076,308.25389 783.97076,309.05075 C 783.97076,309.77733 784.17388,310.33006 784.58014,310.70895 C 784.98638,311.08787 785.98248,311.48045 787.56842,311.88669 L 790.19342,312.53122 C 791.81841,312.93748 792.99614,313.57029 793.72662,314.42966 C 794.45708,315.28904 794.82231,316.47263 794.82233,317.98044 C 794.82231,319.74607 794.21294,321.08786 792.9942,322.00583 C 791.77544,322.9238 789.98247,323.38278 787.6153,323.38278 C 786.47466,323.38278 785.34185,323.28513 784.21686,323.08981 C 783.09185,322.8945 781.94732,322.59763 780.78326,322.19919 L 780.78326,322.19919 z"
1164+ transform="matrix(0.9807853,0.1950903,-0.1950903,0.9807853,0,0)"
1165+ id="text3827"
1166+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1167+ <path
1168+ d="M 830.02612,118.37805 L 830.02612,114.22961 L 831.5144,114.22961 C 831.74096,115.54212 832.27612,116.52259 833.11987,117.17102 C 833.96362,117.81946 835.13158,118.14368 836.62378,118.14368 C 837.83471,118.14368 838.75658,117.91321 839.3894,117.45227 C 840.0222,116.99134 840.33861,116.31555 840.33862,115.42493 C 840.33861,114.72181 840.12377,114.17493 839.69409,113.7843 C 839.26439,113.39368 838.37768,113.0304 837.03394,112.69446 L 834.40894,112.04993 C 832.69799,111.61243 831.49487,111.00501 830.79956,110.22766 C 830.10425,109.45033 829.75659,108.34291 829.75659,106.9054 C 829.75659,105.17103 830.33276,103.82143 831.48511,102.85657 C 832.63745,101.89174 834.25268,101.40932 836.33081,101.4093 C 837.35424,101.40932 838.41869,101.49526 839.52417,101.66711 C 840.62963,101.83901 841.77611,102.09682 842.96362,102.44055 L 842.96362,106.30774 L 841.47534,106.30774 C 841.24877,105.10463 840.75267,104.22377 839.98706,103.66516 C 839.22142,103.10658 838.13158,102.82729 836.71753,102.82727 C 835.56127,102.82729 834.68823,103.02846 834.09839,103.43079 C 833.50854,103.83315 833.21362,104.43275 833.21362,105.22961 C 833.21362,105.95619 833.41674,106.50892 833.823,106.88782 C 834.22924,107.26674 835.22533,107.65931 836.81128,108.06555 L 839.43628,108.71008 C 841.06127,109.11634 842.239,109.74915 842.96948,110.60852 C 843.69994,111.4679 844.06517,112.6515 844.06519,114.1593 C 844.06517,115.92493 843.4558,117.26673 842.23706,118.18469 C 841.0183,119.10266 839.22533,119.56165 836.85815,119.56165 C 835.71752,119.56165 834.58471,119.46399 833.45972,119.26868 C 832.33471,119.07336 831.19018,118.77649 830.02612,118.37805 L 830.02612,118.37805 z M 855.95972,118.14368 C 857.45189,118.14368 858.56127,117.51477 859.28784,116.25696 C 860.01439,114.99915 860.37767,113.07728 860.37769,110.49133 C 860.37767,107.89759 860.01439,105.97182 859.28784,104.71399 C 858.56127,103.45619 857.45189,102.82729 855.95972,102.82727 C 854.47533,102.82729 853.36791,103.46205 852.63745,104.73157 C 851.90698,106.00111 851.54174,107.92103 851.54175,110.49133 C 851.54174,113.05384 851.90698,114.96985 852.63745,116.23938 C 853.36791,117.50891 854.47533,118.14368 855.95972,118.14368 L 855.95972,118.14368 z M 855.95972,119.56165 C 853.0144,119.56165 850.70581,118.75696 849.03394,117.14758 C 847.36206,115.53821 846.52612,113.31946 846.52612,110.49133 C 846.52612,107.66322 847.36401,105.44252 849.03979,103.82922 C 850.71557,102.21596 853.02221,101.40932 855.95972,101.4093 C 858.90502,101.40932 861.21361,102.21401 862.8855,103.82336 C 864.55735,105.43275 865.39329,107.65541 865.39331,110.49133 C 865.39329,113.31946 864.5554,115.53821 862.87964,117.14758 C 861.20384,118.75696 858.8972,119.56165 855.95972,119.56165 L 855.95972,119.56165 z M 867.26831,119.2218 L 867.26831,117.80383 L 874.41675,108.13586 L 869.03784,108.13586 L 869.03784,110.26868 L 867.64331,110.26868 L 867.64331,106.76477 L 879.24487,106.76477 L 879.24487,108.1593 L 872.08472,117.82727 L 877.85034,117.82727 L 877.85034,115.57727 L 879.24487,115.57727 L 879.24487,119.2218 L 867.26831,119.2218 z M 890.50659,118.14368 C 891.99877,118.14368 893.10814,117.51477 893.83472,116.25696 C 894.56126,114.99915 894.92455,113.07728 894.92456,110.49133 C 894.92455,107.89759 894.56126,105.97182 893.83472,104.71399 C 893.10814,103.45619 891.99877,102.82729 890.50659,102.82727 C 889.02221,102.82729 887.91479,103.46205 887.18433,104.73157 C 886.45385,106.00111 886.08862,107.92103 886.08862,110.49133 C 886.08862,113.05384 886.45385,114.96985 887.18433,116.23938 C 887.91479,117.50891 889.02221,118.14368 890.50659,118.14368 L 890.50659,118.14368 z M 890.50659,119.56165 C 887.56127,119.56165 885.25268,118.75696 883.58081,117.14758 C 881.90893,115.53821 881.073,113.31946 881.073,110.49133 C 881.073,107.66322 881.91089,105.44252 883.58667,103.82922 C 885.26245,102.21596 887.56908,101.40932 890.50659,101.4093 C 893.45189,101.40932 895.76048,102.21401 897.43237,103.82336 C 899.10423,105.43275 899.94017,107.65541 899.94019,110.49133 C 899.94017,113.31946 899.10228,115.53821 897.42651,117.14758 C 895.75072,118.75696 893.44408,119.56165 890.50659,119.56165 L 890.50659,119.56165 z"
1169+ transform="matrix(0.8314696,0.5555702,-0.5555702,0.8314696,0,0)"
1170+ id="text3831"
1171+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1172+ <path
1173+ d="M 830.01257,-102.41483 L 830.01257,-106.56327 L 831.50085,-106.56327 C 831.72741,-105.25077 832.26257,-104.2703 833.10632,-103.62186 C 833.95007,-102.97343 835.11804,-102.64921 836.61023,-102.64921 C 837.82116,-102.64921 838.74303,-102.87968 839.37585,-103.34061 C 840.00866,-103.80155 840.32506,-104.47733 840.32507,-105.36796 C 840.32506,-106.07108 840.11022,-106.61795 839.68054,-107.00858 C 839.25084,-107.3992 838.36413,-107.76248 837.02039,-108.09843 L 834.39539,-108.74296 C 832.68444,-109.18045 831.48132,-109.78787 830.78601,-110.56522 C 830.0907,-111.34256 829.74304,-112.44998 829.74304,-113.88749 C 829.74304,-115.62185 830.31921,-116.97146 831.47156,-117.93632 C 832.6239,-118.90114 834.23913,-119.38357 836.31726,-119.38358 C 837.34069,-119.38357 838.40514,-119.29763 839.51062,-119.12577 C 840.61608,-118.95388 841.76256,-118.69607 842.95007,-118.35233 L 842.95007,-114.48515 L 841.46179,-114.48515 C 841.23522,-115.68826 840.73912,-116.56911 839.97351,-117.12772 C 839.20787,-117.6863 838.11803,-117.9656 836.70398,-117.96561 C 835.54772,-117.9656 834.67468,-117.76443 834.08484,-117.3621 C 833.49499,-116.95974 833.20007,-116.36013 833.20007,-115.56327 C 833.20007,-114.83669 833.40319,-114.28396 833.80945,-113.90507 C 834.21569,-113.52615 835.21178,-113.13357 836.79773,-112.72733 L 839.42273,-112.0828 C 841.04772,-111.67654 842.22545,-111.04373 842.95593,-110.18436 C 843.68639,-109.32498 844.05162,-108.14139 844.05164,-106.63358 C 844.05162,-104.86795 843.44225,-103.52616 842.22351,-102.60819 C 841.00475,-101.69022 839.21178,-101.23124 836.8446,-101.23124 C 835.70397,-101.23124 834.57116,-101.3289 833.44617,-101.52421 C 832.32116,-101.71952 831.17663,-102.0164 830.01257,-102.41483 L 830.01257,-102.41483 z M 855.94617,-102.64921 C 857.43834,-102.64921 858.54772,-103.27811 859.27429,-104.53593 C 860.00084,-105.79374 860.36412,-107.71561 860.36414,-110.30155 C 860.36412,-112.89529 860.00084,-114.82107 859.27429,-116.0789 C 858.54772,-117.33669 857.43834,-117.9656 855.94617,-117.96561 C 854.46178,-117.9656 853.35436,-117.33083 852.6239,-116.06132 C 851.89343,-114.79177 851.52819,-112.87185 851.5282,-110.30155 C 851.52819,-107.73905 851.89343,-105.82303 852.6239,-104.5535 C 853.35436,-103.28397 854.46178,-102.64921 855.94617,-102.64921 L 855.94617,-102.64921 z M 855.94617,-101.23124 C 853.00085,-101.23124 850.69226,-102.03593 849.02039,-103.6453 C 847.34851,-105.25467 846.51257,-107.47342 846.51257,-110.30155 C 846.51257,-113.12967 847.35046,-115.35037 849.02625,-116.96366 C 850.70202,-118.57693 853.00866,-119.38357 855.94617,-119.38358 C 858.89147,-119.38357 861.20006,-118.57888 862.87195,-116.96952 C 864.5438,-115.36013 865.37974,-113.13748 865.37976,-110.30155 C 865.37974,-107.47342 864.54185,-105.25467 862.86609,-103.6453 C 861.19029,-102.03593 858.88365,-101.23124 855.94617,-101.23124 L 855.94617,-101.23124 z M 867.25476,-101.57108 L 867.25476,-102.98905 L 874.4032,-112.65702 L 869.02429,-112.65702 L 869.02429,-110.52421 L 867.62976,-110.52421 L 867.62976,-114.02811 L 879.23132,-114.02811 L 879.23132,-112.63358 L 872.07117,-102.96561 L 877.83679,-102.96561 L 877.83679,-105.21561 L 879.23132,-105.21561 L 879.23132,-101.57108 L 867.25476,-101.57108 z M 881.9032,-102.41483 L 881.9032,-106.56327 L 883.39148,-106.56327 C 883.61804,-105.25077 884.15319,-104.2703 884.99695,-103.62186 C 885.84069,-102.97343 887.00866,-102.64921 888.50085,-102.64921 C 889.71178,-102.64921 890.63366,-102.87968 891.26648,-103.34061 C 891.89928,-103.80155 892.21569,-104.47733 892.2157,-105.36796 C 892.21569,-106.07108 892.00084,-106.61795 891.57117,-107.00858 C 891.14147,-107.3992 890.25475,-107.76248 888.91101,-108.09843 L 886.28601,-108.74296 C 884.57507,-109.18045 883.37194,-109.78787 882.67664,-110.56522 C 881.98132,-111.34256 881.63367,-112.44998 881.63367,-113.88749 C 881.63367,-115.62185 882.20984,-116.97146 883.36218,-117.93632 C 884.51452,-118.90114 886.12975,-119.38357 888.20789,-119.38358 C 889.23131,-119.38357 890.29577,-119.29763 891.40125,-119.12577 C 892.5067,-118.95388 893.65318,-118.69607 894.8407,-118.35233 L 894.8407,-114.48515 L 893.35242,-114.48515 C 893.12584,-115.68826 892.62975,-116.56911 891.86414,-117.12772 C 891.0985,-117.6863 890.00866,-117.9656 888.5946,-117.96561 C 887.43835,-117.9656 886.5653,-117.76443 885.97546,-117.3621 C 885.38561,-116.95974 885.09069,-116.36013 885.0907,-115.56327 C 885.09069,-114.83669 885.29382,-114.28396 885.70007,-113.90507 C 886.10632,-113.52615 887.10241,-113.13357 888.68835,-112.72733 L 891.31335,-112.0828 C 892.93834,-111.67654 894.11607,-111.04373 894.84656,-110.18436 C 895.57701,-109.32498 895.94224,-108.14139 895.94226,-106.63358 C 895.94224,-104.86795 895.33287,-103.52616 894.11414,-102.60819 C 892.89537,-101.69022 891.10241,-101.23124 888.73523,-101.23124 C 887.5946,-101.23124 886.46179,-101.3289 885.33679,-101.52421 C 884.21179,-101.71952 883.06726,-102.0164 881.9032,-102.41483 L 881.9032,-102.41483 z"
1174+ transform="matrix(0.5555702,0.8314696,-0.8314696,0.5555702,0,0)"
1175+ id="text3835"
1176+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1177+ <path
1178+ d="M 745.54657,-306.64249 L 745.54657,-310.79092 L 747.03485,-310.79092 C 747.26141,-309.47842 747.79657,-308.49795 748.64032,-307.84952 C 749.48406,-307.20108 750.65203,-306.87686 752.14423,-306.87686 C 753.35515,-306.87686 754.27703,-307.10733 754.90985,-307.56827 C 755.54265,-308.0292 755.85906,-308.70498 755.85907,-309.59561 C 755.85906,-310.29873 755.64421,-310.84561 755.21454,-311.23624 C 754.78484,-311.62686 753.89812,-311.99014 752.55438,-312.32608 L 749.92938,-312.97061 C 748.21844,-313.4081 747.01532,-314.01553 746.32001,-314.79288 C 745.62469,-315.57021 745.27704,-316.67763 745.27704,-318.11514 C 745.27704,-319.8495 745.85321,-321.19911 747.00555,-322.16397 C 748.15789,-323.1288 749.77313,-323.61122 751.85126,-323.61124 C 752.87469,-323.61122 753.93914,-323.52528 755.04462,-323.35342 C 756.15007,-323.18153 757.29656,-322.92372 758.48407,-322.57999 L 758.48407,-318.7128 L 756.99579,-318.7128 C 756.76921,-319.91591 756.27312,-320.79677 755.50751,-321.35538 C 754.74187,-321.91395 753.65203,-322.19325 752.23798,-322.19327 C 751.08172,-322.19325 750.20867,-321.99208 749.61884,-321.58975 C 749.02899,-321.18739 748.73406,-320.58778 748.73407,-319.79092 C 748.73406,-319.06435 748.93719,-318.51161 749.34344,-318.13272 C 749.74969,-317.7538 750.74578,-317.36123 752.33173,-316.95499 L 754.95673,-316.31046 C 756.58171,-315.9042 757.75945,-315.27138 758.48993,-314.41202 C 759.22038,-313.55264 759.58562,-312.36904 759.58563,-310.86124 C 759.58562,-309.09561 758.97624,-307.75381 757.75751,-306.83585 C 756.53874,-305.91788 754.74578,-305.45889 752.3786,-305.45889 C 751.23797,-305.45889 750.10516,-305.55655 748.98016,-305.75186 C 747.85516,-305.94717 746.71063,-306.24405 745.54657,-306.64249 L 745.54657,-306.64249 z M 761.88251,-305.79874 L 761.88251,-307.21671 L 769.03094,-316.88467 L 763.65204,-316.88467 L 763.65204,-314.75186 L 762.25751,-314.75186 L 762.25751,-318.25577 L 773.85907,-318.25577 L 773.85907,-316.86124 L 766.69891,-307.19327 L 772.46454,-307.19327 L 772.46454,-309.44327 L 773.85907,-309.44327 L 773.85907,-305.79874 L 761.88251,-305.79874 z M 785.12079,-306.87686 C 786.61296,-306.87686 787.72234,-307.50577 788.44891,-308.76358 C 789.17546,-310.02139 789.53874,-311.94326 789.53876,-314.52921 C 789.53874,-317.12294 789.17546,-319.04872 788.44891,-320.30655 C 787.72234,-321.56435 786.61296,-322.19325 785.12079,-322.19327 C 783.6364,-322.19325 782.52898,-321.55849 781.79852,-320.28897 C 781.06805,-319.01943 780.70281,-317.09951 780.70282,-314.52921 C 780.70281,-311.9667 781.06805,-310.05069 781.79852,-308.78116 C 782.52898,-307.51163 783.6364,-306.87686 785.12079,-306.87686 L 785.12079,-306.87686 z M 785.12079,-305.45889 C 782.17547,-305.45889 779.86688,-306.26358 778.19501,-307.87296 C 776.52313,-309.48233 775.68719,-311.70107 775.68719,-314.52921 C 775.68719,-317.35732 776.52508,-319.57802 778.20087,-321.19131 C 779.87664,-322.80458 782.18328,-323.61122 785.12079,-323.61124 C 788.06609,-323.61122 790.37468,-322.80653 792.04657,-321.19717 C 793.71843,-319.58779 794.55436,-317.36513 794.55438,-314.52921 C 794.55436,-311.70107 793.71647,-309.48233 792.04071,-307.87296 C 790.36491,-306.26358 788.05828,-305.45889 785.12079,-305.45889 L 785.12079,-305.45889 z"
1179+ transform="matrix(0.1950903,0.9807853,-0.9807853,0.1950903,0,0)"
1180+ id="text3839"
1181+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1182+ <path
1183+ d="M -645.54681,478.55106 L -645.54681,474.40262 L -644.05853,474.40262 C -643.83197,475.71512 -643.29682,476.69559 -642.45306,477.34402 C -641.60932,477.99246 -640.44135,478.31668 -638.94916,478.31668 C -637.73823,478.31668 -636.81636,478.08621 -636.18353,477.62527 C -635.55073,477.16434 -635.23433,476.48856 -635.23431,475.59793 C -635.23433,474.89481 -635.44917,474.34794 -635.87885,473.95731 C -636.30854,473.56669 -637.19526,473.20341 -638.539,472.86746 L -641.164,472.22293 C -642.87494,471.78544 -644.07807,471.17802 -644.77338,470.40067 C -645.46869,469.62333 -645.81635,468.51591 -645.81635,467.0784 C -645.81635,465.34404 -645.24018,463.99443 -644.08783,463.02957 C -642.93549,462.06475 -641.32026,461.58232 -639.24213,461.58231 C -638.2187,461.58232 -637.15425,461.66826 -636.04877,461.84012 C -634.94331,462.01201 -633.79683,462.26982 -632.60931,462.61356 L -632.60931,466.48074 L -634.0976,466.48074 C -634.32417,465.27763 -634.82026,464.39677 -635.58588,463.83817 C -636.35151,463.27959 -637.44136,463.00029 -638.85541,463.00027 C -640.01167,463.00029 -640.88471,463.20146 -641.47455,463.60379 C -642.0644,464.00615 -642.35932,464.60576 -642.35931,465.40262 C -642.35932,466.12919 -642.15619,466.68193 -641.74994,467.06082 C -641.3437,467.43974 -640.3476,467.83232 -638.76166,468.23856 L -636.13666,468.88309 C -634.51167,469.28935 -633.33394,469.92216 -632.60345,470.78152 C -631.873,471.64091 -631.50777,472.8245 -631.50775,474.33231 C -631.50777,476.09793 -632.11714,477.43973 -633.33588,478.3577 C -634.55464,479.27567 -636.34761,479.73465 -638.71478,479.73465 C -639.85542,479.73465 -640.98823,479.63699 -642.11322,479.44168 C -643.23822,479.24637 -644.38275,478.94949 -645.54681,478.55106 L -645.54681,478.55106 z M -629.21088,479.39481 L -629.21088,477.97684 L -622.06244,468.30887 L -627.44135,468.30887 L -627.44135,470.44168 L -628.83588,470.44168 L -628.83588,466.93777 L -617.23431,466.93777 L -617.23431,468.33231 L -624.39447,478.00027 L -618.62885,478.00027 L -618.62885,475.75027 L -617.23431,475.75027 L -617.23431,479.39481 L -629.21088,479.39481 z M -595.96478,479.39481 L -598.98822,479.39481 L -602.94916,466.65652 L -606.9101,479.39481 L -609.93353,479.39481 L -614.92572,463.31668 L -616.62494,463.31668 L -616.62494,461.89871 L -608.32806,461.89871 L -608.32806,463.31668 L -610.20306,463.31668 L -606.86322,474.06277 L -603.08978,461.89871 L -599.76166,461.89871 L -595.91791,474.26199 L -592.50775,463.31668 L -594.59369,463.31668 L -594.59369,461.89871 L -589.17963,461.89871 L -589.17963,463.31668 L -590.9726,463.31668 L -595.96478,479.39481 z"
1184+ transform="matrix(0.1950903,-0.9807853,0.9807853,0.1950903,0,0)"
1185+ id="text3843"
1186+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1187+ <path
1188+ d="M -457.32495,562.52277 L -457.32495,558.37433 L -455.83667,558.37433 C -455.61011,559.68683 -455.07496,560.6673 -454.2312,561.31573 C -453.38746,561.96417 -452.21949,562.28839 -450.72729,562.28839 C -449.51637,562.28839 -448.59449,562.05792 -447.96167,561.59698 C -447.32887,561.13605 -447.01246,560.46027 -447.01245,559.56964 C -447.01246,558.86652 -447.22731,558.31965 -447.65698,557.92902 C -448.08668,557.5384 -448.9734,557.17512 -450.31714,556.83917 L -452.94214,556.19464 C -454.65308,555.75715 -455.8562,555.14973 -456.55151,554.37238 C -457.24683,553.59504 -457.59448,552.48762 -457.59448,551.05011 C -457.59448,549.31575 -457.01831,547.96614 -455.86597,547.00128 C -454.71363,546.03646 -453.09839,545.55403 -451.02026,545.55402 C -449.99684,545.55403 -448.93238,545.63997 -447.8269,545.81183 C -446.72145,545.98372 -445.57496,546.24153 -444.38745,546.58527 L -444.38745,550.45245 L -445.87573,550.45245 C -446.10231,549.24934 -446.5984,548.36848 -447.36401,547.80988 C -448.12965,547.2513 -449.21949,546.972 -450.63354,546.97198 C -451.7898,546.972 -452.66285,547.17317 -453.25269,547.5755 C -453.84253,547.97786 -454.13746,548.57747 -454.13745,549.37433 C -454.13746,550.1009 -453.93433,550.65364 -453.52808,551.03253 C -453.12183,551.41145 -452.12574,551.80403 -450.53979,552.21027 L -447.91479,552.8548 C -446.28981,553.26106 -445.11207,553.89387 -444.38159,554.75323 C -443.65114,555.61262 -443.2859,556.79621 -443.28589,558.30402 C -443.2859,560.06964 -443.89528,561.41144 -445.11401,562.32941 C -446.33278,563.24738 -448.12574,563.70636 -450.49292,563.70636 C -451.63355,563.70636 -452.76636,563.6087 -453.89136,563.41339 C -455.01636,563.21808 -456.16089,562.9212 -457.32495,562.52277 L -457.32495,562.52277 z M -421.38354,563.36652 L -424.40698,563.36652 L -428.36792,550.62823 L -432.32886,563.36652 L -435.35229,563.36652 L -440.34448,547.28839 L -442.0437,547.28839 L -442.0437,545.87042 L -433.74683,545.87042 L -433.74683,547.28839 L -435.62183,547.28839 L -432.28198,558.03448 L -428.50854,545.87042 L -425.18042,545.87042 L -421.33667,558.2337 L -417.92651,547.28839 L -420.01245,547.28839 L -420.01245,545.87042 L -414.59839,545.87042 L -414.59839,547.28839 L -416.39136,547.28839 L -421.38354,563.36652 z M -414.03589,563.36652 L -414.03589,561.94855 L -406.88745,552.28058 L -412.26636,552.28058 L -412.26636,554.41339 L -413.66089,554.41339 L -413.66089,550.90948 L -402.05933,550.90948 L -402.05933,552.30402 L -409.21948,561.97198 L -403.45386,561.97198 L -403.45386,559.72198 L -402.05933,559.72198 L -402.05933,563.36652 L -414.03589,563.36652 z M -399.38745,562.52277 L -399.38745,558.37433 L -397.89917,558.37433 C -397.67261,559.68683 -397.13746,560.6673 -396.2937,561.31573 C -395.44996,561.96417 -394.28199,562.28839 -392.78979,562.28839 C -391.57887,562.28839 -390.65699,562.05792 -390.02417,561.59698 C -389.39137,561.13605 -389.07496,560.46027 -389.07495,559.56964 C -389.07496,558.86652 -389.28981,558.31965 -389.71948,557.92902 C -390.14918,557.5384 -391.0359,557.17512 -392.37964,556.83917 L -395.00464,556.19464 C -396.71558,555.75715 -397.9187,555.14973 -398.61401,554.37238 C -399.30933,553.59504 -399.65698,552.48762 -399.65698,551.05011 C -399.65698,549.31575 -399.08081,547.96614 -397.92847,547.00128 C -396.77613,546.03646 -395.16089,545.55403 -393.08276,545.55402 C -392.05934,545.55403 -390.99488,545.63997 -389.8894,545.81183 C -388.78395,545.98372 -387.63746,546.24153 -386.44995,546.58527 L -386.44995,550.45245 L -387.93823,550.45245 C -388.16481,549.24934 -388.6609,548.36848 -389.42651,547.80988 C -390.19215,547.2513 -391.28199,546.972 -392.69604,546.97198 C -393.8523,546.972 -394.72535,547.17317 -395.31519,547.5755 C -395.90503,547.97786 -396.19996,548.57747 -396.19995,549.37433 C -396.19996,550.1009 -395.99683,550.65364 -395.59058,551.03253 C -395.18433,551.41145 -394.18824,551.80403 -392.60229,552.21027 L -389.97729,552.8548 C -388.35231,553.26106 -387.17457,553.89387 -386.44409,554.75323 C -385.71364,555.61262 -385.3484,556.79621 -385.34839,558.30402 C -385.3484,560.06964 -385.95778,561.41144 -387.17651,562.32941 C -388.39528,563.24738 -390.18824,563.70636 -392.55542,563.70636 C -393.69605,563.70636 -394.82886,563.6087 -395.95386,563.41339 C -397.07886,563.21808 -398.22339,562.9212 -399.38745,562.52277 L -399.38745,562.52277 z"
1189+ transform="matrix(0.5555702,-0.8314696,0.8314696,0.5555702,0,0)"
1190+ id="text3847"
1191+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1192+ <path
1193+ d="M -247.79565,562.72998 L -247.79565,558.58154 L -246.30737,558.58154 C -246.08081,559.89405 -245.54566,560.87451 -244.7019,561.52295 C -243.85816,562.17139 -242.69019,562.49561 -241.198,562.49561 C -239.98707,562.49561 -239.0652,562.26514 -238.43237,561.8042 C -237.79957,561.34326 -237.48317,560.66748 -237.48315,559.77686 C -237.48317,559.07373 -237.69801,558.52686 -238.12769,558.13623 C -238.55738,557.74561 -239.4441,557.38233 -240.78784,557.04639 L -243.41284,556.40186 C -245.12378,555.96436 -246.32691,555.35694 -247.02222,554.57959 C -247.71753,553.80226 -248.06519,552.69484 -248.06519,551.25732 C -248.06519,549.52296 -247.48902,548.17336 -246.33667,547.2085 C -245.18433,546.24367 -243.5691,545.76125 -241.49097,545.76123 C -240.46754,545.76125 -239.40309,545.84719 -238.29761,546.01904 C -237.19215,546.19094 -236.04567,546.44875 -234.85815,546.79248 L -234.85815,550.65967 L -236.34644,550.65967 C -236.57301,549.45656 -237.0691,548.5757 -237.83472,548.01709 C -238.60035,547.45851 -239.6902,547.17922 -241.10425,547.1792 C -242.26051,547.17922 -243.13355,547.38039 -243.72339,547.78271 C -244.31324,548.18507 -244.60816,548.78468 -244.60815,549.58154 C -244.60816,550.30812 -244.40503,550.86085 -243.99878,551.23975 C -243.59254,551.61866 -242.59644,552.01124 -241.0105,552.41748 L -238.3855,553.06201 C -236.76051,553.46827 -235.58278,554.10108 -234.85229,554.96045 C -234.12184,555.81983 -233.75661,557.00342 -233.75659,558.51123 C -233.75661,560.27686 -234.36598,561.61865 -235.58472,562.53662 C -236.80348,563.45459 -238.59645,563.91357 -240.96362,563.91357 C -242.10426,563.91357 -243.23707,563.81592 -244.36206,563.62061 C -245.48706,563.42529 -246.63159,563.12842 -247.79565,562.72998 L -247.79565,562.72998 z M -211.85425,563.57373 L -214.87769,563.57373 L -218.83862,550.83545 L -222.79956,563.57373 L -225.823,563.57373 L -230.81519,547.49561 L -232.5144,547.49561 L -232.5144,546.07764 L -224.21753,546.07764 L -224.21753,547.49561 L -226.09253,547.49561 L -222.75269,558.2417 L -218.97925,546.07764 L -215.65112,546.07764 L -211.80737,558.44092 L -208.39722,547.49561 L -210.48315,547.49561 L -210.48315,546.07764 L -205.06909,546.07764 L -205.06909,547.49561 L -206.86206,547.49561 L -211.85425,563.57373 z M -204.50659,563.57373 L -204.50659,562.15576 L -197.35815,552.48779 L -202.73706,552.48779 L -202.73706,554.62061 L -204.13159,554.62061 L -204.13159,551.1167 L -192.53003,551.1167 L -192.53003,552.51123 L -199.69019,562.1792 L -193.92456,562.1792 L -193.92456,559.9292 L -192.53003,559.9292 L -192.53003,563.57373 L -204.50659,563.57373 z M -171.2605,563.57373 L -174.28394,563.57373 L -178.24487,550.83545 L -182.20581,563.57373 L -185.22925,563.57373 L -190.22144,547.49561 L -191.92065,547.49561 L -191.92065,546.07764 L -183.62378,546.07764 L -183.62378,547.49561 L -185.49878,547.49561 L -182.15894,558.2417 L -178.3855,546.07764 L -175.05737,546.07764 L -171.21362,558.44092 L -167.80347,547.49561 L -169.8894,547.49561 L -169.8894,546.07764 L -164.47534,546.07764 L -164.47534,547.49561 L -166.26831,547.49561 L -171.2605,563.57373 z"
1194+ transform="matrix(0.8314696,-0.5555702,0.5555702,0.8314696,0,0)"
1195+ id="text3851"
1196+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1197+ <path
1198+ d="M 3.1841583,479.50815 L 0.16072083,479.50815 L -3.8002167,466.76987 L -7.7611542,479.50815 L -10.784592,479.50815 L -15.776779,463.43002 L -17.475998,463.43002 L -17.475998,462.01205 L -9.1791229,462.01205 L -9.1791229,463.43002 L -11.054123,463.43002 L -7.7142792,474.17612 L -3.9408417,462.01205 L -0.61271667,462.01205 L 3.2310333,474.37534 L 6.6411896,463.43002 L 4.5552521,463.43002 L 4.5552521,462.01205 L 9.9693146,462.01205 L 9.9693146,463.43002 L 8.1763458,463.43002 L 3.1841583,479.50815 z M 10.531815,479.50815 L 10.531815,478.09018 L 17.680252,468.42221 L 12.301346,468.42221 L 12.301346,470.55502 L 10.906815,470.55502 L 10.906815,467.05112 L 22.508377,467.05112 L 22.508377,468.44565 L 15.348221,478.11362 L 21.113846,478.11362 L 21.113846,475.86362 L 22.508377,475.86362 L 22.508377,479.50815 L 10.531815,479.50815 z M 25.180252,478.6644 L 25.180252,474.51596 L 26.668533,474.51596 C 26.895092,475.82846 27.430248,476.80893 28.274002,477.45737 C 29.117746,478.10581 30.285714,478.43002 31.777908,478.43002 C 32.988836,478.43002 33.91071,478.19956 34.543533,477.73862 C 35.176334,477.27768 35.49274,476.6019 35.492752,475.71127 C 35.49274,475.00815 35.277896,474.46128 34.848221,474.07065 C 34.418522,473.68003 33.531804,473.31675 32.188065,472.9808 L 29.563065,472.33627 C 27.852123,471.89878 26.648999,471.29136 25.95369,470.51401 C 25.258375,469.73667 24.910719,468.62925 24.910721,467.19174 C 24.910719,465.45738 25.486891,464.10777 26.639236,463.14291 C 27.791576,462.17809 29.406808,461.69567 31.48494,461.69565 C 32.508368,461.69567 33.57282,461.7816 34.678299,461.95346 C 35.783755,462.12535 36.930238,462.38317 38.117752,462.7269 L 38.117752,466.59409 L 36.629471,466.59409 C 36.402895,465.39097 35.906802,464.51012 35.14119,463.95151 C 34.375554,463.39293 33.285711,463.11363 31.871658,463.11362 C 30.715401,463.11363 29.842355,463.31481 29.252518,463.71713 C 28.662669,464.11949 28.367747,464.7191 28.367752,465.51596 C 28.367747,466.24254 28.570872,466.79527 28.977127,467.17416 C 29.383371,467.55308 30.379464,467.94566 31.965408,468.3519 L 34.590408,468.99643 C 36.215395,469.40269 37.393129,470.0355 38.123611,470.89487 C 38.854065,471.75425 39.219299,472.93784 39.219315,474.44565 C 39.219299,476.21128 38.609924,477.55307 37.39119,478.47104 C 36.172427,479.38901 34.37946,479.84799 32.012283,479.84799 C 30.871651,479.84799 29.738839,479.75034 28.613846,479.55502 C 27.488842,479.35971 26.344312,479.06284 25.180252,478.6644 L 25.180252,478.6644 z"
1199+ transform="matrix(0.9807853,-0.1950903,0.1950903,0.9807853,0,0)"
1200+ id="text3855"
1201+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1202+ <path
1203+ d="M 154.29852,323.11514 L 151.27509,323.11514 L 147.31415,310.37686 L 143.35321,323.11514 L 140.32977,323.11514 L 135.33759,307.03702 L 133.63837,307.03702 L 133.63837,305.61905 L 141.93524,305.61905 L 141.93524,307.03702 L 140.06024,307.03702 L 143.40009,317.78311 L 147.17352,305.61905 L 150.50165,305.61905 L 154.3454,317.98233 L 157.75555,307.03702 L 155.66962,307.03702 L 155.66962,305.61905 L 161.08368,305.61905 L 161.08368,307.03702 L 159.29071,307.03702 L 154.29852,323.11514 z M 161.64618,323.11514 L 161.64618,321.69717 L 168.79462,312.02921 L 163.41571,312.02921 L 163.41571,314.16202 L 162.02118,314.16202 L 162.02118,310.65811 L 173.62274,310.65811 L 173.62274,312.05264 L 166.46259,321.72061 L 172.22821,321.72061 L 172.22821,319.47061 L 173.62274,319.47061 L 173.62274,323.11514 L 161.64618,323.11514 z M 175.49774,323.11514 L 175.49774,321.69717 L 177.73602,321.69717 L 177.73602,307.03702 L 175.49774,307.03702 L 175.49774,305.61905 L 180.9704,305.61905 L 191.52899,318.00577 L 191.52899,307.03702 L 189.30243,307.03702 L 189.30243,305.61905 L 195.41962,305.61905 L 195.41962,307.03702 L 193.18134,307.03702 L 193.18134,323.11514 L 190.11102,323.11514 L 179.38837,310.47061 L 179.38837,321.69717 L 181.61493,321.69717 L 181.61493,323.11514 L 175.49774,323.11514 z"
1204+ transform="matrix(0.9807853,0.1950903,-0.1950903,0.9807853,0,0)"
1205+ id="text3859"
1206+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1207+ <path
1208+ d="M 191.22664,119.73893 L 191.22664,118.32096 L 193.46492,118.32096 L 193.46492,103.6608 L 191.22664,103.6608 L 191.22664,102.24284 L 196.6993,102.24284 L 207.25789,114.62955 L 207.25789,103.6608 L 205.03133,103.6608 L 205.03133,102.24284 L 211.14851,102.24284 L 211.14851,103.6608 L 208.91023,103.6608 L 208.91023,119.73893 L 205.83992,119.73893 L 195.11726,107.0944 L 195.11726,118.32096 L 197.34383,118.32096 L 197.34383,119.73893 L 191.22664,119.73893 z M 232.55867,119.73893 L 229.53523,119.73893 L 225.5743,107.00065 L 221.61336,119.73893 L 218.58992,119.73893 L 213.59773,103.6608 L 211.89851,103.6608 L 211.89851,102.24284 L 220.19539,102.24284 L 220.19539,103.6608 L 218.32039,103.6608 L 221.66023,114.4069 L 225.43367,102.24284 L 228.7618,102.24284 L 232.60555,114.60612 L 236.0157,103.6608 L 233.92976,103.6608 L 233.92976,102.24284 L 239.34383,102.24284 L 239.34383,103.6608 L 237.55086,103.6608 L 232.55867,119.73893 z M 239.90633,119.73893 L 239.90633,118.32096 L 247.05476,108.65299 L 241.67586,108.65299 L 241.67586,110.7858 L 240.28133,110.7858 L 240.28133,107.2819 L 251.88289,107.2819 L 251.88289,108.67643 L 244.72273,118.3444 L 250.48836,118.3444 L 250.48836,116.0944 L 251.88289,116.0944 L 251.88289,119.73893 L 239.90633,119.73893 z M 273.15242,119.73893 L 270.12898,119.73893 L 266.16805,107.00065 L 262.20711,119.73893 L 259.18367,119.73893 L 254.19148,103.6608 L 252.49226,103.6608 L 252.49226,102.24284 L 260.78914,102.24284 L 260.78914,103.6608 L 258.91414,103.6608 L 262.25398,114.4069 L 266.02742,102.24284 L 269.35555,102.24284 L 273.1993,114.60612 L 276.60945,103.6608 L 274.52351,103.6608 L 274.52351,102.24284 L 279.93758,102.24284 L 279.93758,103.6608 L 278.14461,103.6608 L 273.15242,119.73893 z"
1209+ transform="matrix(0.8314696,0.5555702,-0.5555702,0.8314696,0,0)"
1210+ id="text3863"
1211+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1212+ <path
1213+ d="M 197.47798,-101.58138 L 197.47798,-102.99935 L 199.71626,-102.99935 L 199.71626,-117.65951 L 197.47798,-117.65951 L 197.47798,-119.07748 L 202.95064,-119.07748 L 213.50923,-106.69076 L 213.50923,-117.65951 L 211.28267,-117.65951 L 211.28267,-119.07748 L 217.39986,-119.07748 L 217.39986,-117.65951 L 215.16158,-117.65951 L 215.16158,-101.58138 L 212.09126,-101.58138 L 201.36861,-114.22591 L 201.36861,-102.99935 L 203.59517,-102.99935 L 203.59517,-101.58138 L 197.47798,-101.58138 z M 238.81001,-101.58138 L 235.78658,-101.58138 L 231.82564,-114.31966 L 227.8647,-101.58138 L 224.84126,-101.58138 L 219.84908,-117.65951 L 218.14986,-117.65951 L 218.14986,-119.07748 L 226.44673,-119.07748 L 226.44673,-117.65951 L 224.57173,-117.65951 L 227.91158,-106.91341 L 231.68501,-119.07748 L 235.01314,-119.07748 L 238.85689,-106.7142 L 242.26704,-117.65951 L 240.18111,-117.65951 L 240.18111,-119.07748 L 245.59517,-119.07748 L 245.59517,-117.65951 L 243.8022,-117.65951 L 238.81001,-101.58138 z M 246.15767,-101.58138 L 246.15767,-102.99935 L 253.30611,-112.66732 L 247.9272,-112.66732 L 247.9272,-110.53451 L 246.53267,-110.53451 L 246.53267,-114.03841 L 258.13423,-114.03841 L 258.13423,-112.64388 L 250.97408,-102.97591 L 256.7397,-102.97591 L 256.7397,-105.22591 L 258.13423,-105.22591 L 258.13423,-101.58138 L 246.15767,-101.58138 z M 260.00923,-101.58138 L 260.00923,-102.99935 L 262.24751,-102.99935 L 262.24751,-117.65951 L 260.00923,-117.65951 L 260.00923,-119.07748 L 265.48189,-119.07748 L 276.04048,-106.69076 L 276.04048,-117.65951 L 273.81392,-117.65951 L 273.81392,-119.07748 L 279.93111,-119.07748 L 279.93111,-117.65951 L 277.69283,-117.65951 L 277.69283,-101.58138 L 274.62251,-101.58138 L 263.89986,-114.22591 L 263.89986,-102.99935 L 266.12642,-102.99935 L 266.12642,-101.58138 L 260.00923,-101.58138 z"
1214+ transform="matrix(0.5555702,0.8314696,-0.8314696,0.5555702,0,0)"
1215+ id="text3867"
1216+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1217+ <path
1218+ d="M 133.63519,-305.5083 L 133.63519,-306.92627 L 135.87347,-306.92627 L 135.87347,-321.58643 L 133.63519,-321.58643 L 133.63519,-323.00439 L 139.10785,-323.00439 L 149.66644,-310.61768 L 149.66644,-321.58643 L 147.43988,-321.58643 L 147.43988,-323.00439 L 153.55707,-323.00439 L 153.55707,-321.58643 L 151.31879,-321.58643 L 151.31879,-305.5083 L 148.24847,-305.5083 L 137.52582,-318.15283 L 137.52582,-306.92627 L 139.75238,-306.92627 L 139.75238,-305.5083 L 133.63519,-305.5083 z M 155.36176,-305.5083 L 155.36176,-306.92627 L 162.51019,-316.59424 L 157.13129,-316.59424 L 157.13129,-314.46143 L 155.73676,-314.46143 L 155.73676,-317.96533 L 167.33832,-317.96533 L 167.33832,-316.5708 L 160.17816,-306.90283 L 165.94379,-306.90283 L 165.94379,-309.15283 L 167.33832,-309.15283 L 167.33832,-305.5083 L 155.36176,-305.5083 z M 188.60785,-305.5083 L 185.58441,-305.5083 L 181.62347,-318.24658 L 177.66254,-305.5083 L 174.6391,-305.5083 L 169.64691,-321.58643 L 167.94769,-321.58643 L 167.94769,-323.00439 L 176.24457,-323.00439 L 176.24457,-321.58643 L 174.36957,-321.58643 L 177.70941,-310.84033 L 181.48285,-323.00439 L 184.81097,-323.00439 L 188.65472,-310.64111 L 192.06488,-321.58643 L 189.97894,-321.58643 L 189.97894,-323.00439 L 195.39301,-323.00439 L 195.39301,-321.58643 L 193.60004,-321.58643 L 188.60785,-305.5083 z"
1219+ transform="matrix(0.1950903,0.9807853,-0.9807853,0.1950903,0,0)"
1220+ id="text3871"
1221+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1222+ <path
1223+ d="M 598.7666,477.63593 C 600.25878,477.63593 601.36815,477.00702 602.09473,475.74921 C 602.82127,474.4914 603.18456,472.56953 603.18457,469.98358 C 603.18456,467.38984 602.82127,465.46406 602.09473,464.20624 C 601.36815,462.94844 600.25878,462.31954 598.7666,462.31952 C 597.28222,462.31954 596.1748,462.9543 595.44434,464.22382 C 594.71386,465.49336 594.34863,467.41328 594.34863,469.98358 C 594.34863,472.54609 594.71386,474.4621 595.44434,475.73163 C 596.1748,477.00116 597.28222,477.63593 598.7666,477.63593 L 598.7666,477.63593 z M 598.7666,479.05389 C 595.82128,479.05389 593.51269,478.24921 591.84082,476.63983 C 590.16894,475.03046 589.33301,472.81171 589.33301,469.98358 C 589.33301,467.15547 590.1709,464.93477 591.84668,463.32147 C 593.52246,461.70821 595.82909,460.90157 598.7666,460.90155 C 601.7119,460.90157 604.02049,461.70625 605.69238,463.31561 C 607.36424,464.925 608.20018,467.14766 608.2002,469.98358 C 608.20018,472.81171 607.36229,475.03046 605.68652,476.63983 C 604.01073,478.24921 601.70409,479.05389 598.7666,479.05389 L 598.7666,479.05389 z M 610.0752,478.71405 L 610.0752,477.29608 L 617.22363,467.62811 L 611.84473,467.62811 L 611.84473,469.76093 L 610.4502,469.76093 L 610.4502,466.25702 L 622.05176,466.25702 L 622.05176,467.65155 L 614.8916,477.31952 L 620.65723,477.31952 L 620.65723,475.06952 L 622.05176,475.06952 L 622.05176,478.71405 L 610.0752,478.71405 z M 623.92676,478.71405 L 623.92676,477.29608 L 626.16504,477.29608 L 626.16504,462.63593 L 623.92676,462.63593 L 623.92676,461.21796 L 629.39941,461.21796 L 639.95801,473.60468 L 639.95801,462.63593 L 637.73145,462.63593 L 637.73145,461.21796 L 643.84863,461.21796 L 643.84863,462.63593 L 641.61035,462.63593 L 641.61035,478.71405 L 638.54004,478.71405 L 627.81738,466.06952 L 627.81738,477.29608 L 630.04395,477.29608 L 630.04395,478.71405 L 623.92676,478.71405 z"
1224+ transform="matrix(0.9807853,-0.1950903,0.1950903,0.9807853,0,0)"
1225+ id="text3875"
1226+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Bold" />
1227+ </g>
1228+ </g>
1229+ </g>
1230+ </g>
1231+</svg>
1232
1233=== added file 'snappy/snapcraft.yaml'
1234--- snappy/snapcraft.yaml 1970-01-01 00:00:00 +0000
1235+++ snappy/snapcraft.yaml 2016-01-25 14:24:35 +0000
1236@@ -0,0 +1,47 @@
1237+name: location-service
1238+version: 0.0.1
1239+vendor: 'Thomas Voß <thomas.voss@canonical.com>'
1240+summary: Location service mediates access to positioning providers.
1241+description: Location service mediates access to positioning providers.
1242+type: framework
1243+icon: icon.svg
1244+services:
1245+ location-service:
1246+ security-template: unconfined
1247+ start: bin/ubuntu-location-serviced --bus system --provider dummy
1248+ bus-name: com.ubuntu.location.Service
1249+
1250+parts:
1251+ location-service:
1252+ plugin: cmake
1253+ configflags:
1254+ - -DCMAKE_VERBOSE_MAKEFILE=ON
1255+ source: ../
1256+ stage-packages:
1257+ - curl
1258+ - libdbus-cpp-dev
1259+ - doxygen
1260+ - geoclue-ubuntu-geoip
1261+ - google-mock
1262+ - graphviz
1263+ - libapparmor-dev
1264+ - libboost-filesystem-dev
1265+ - libboost-program-options-dev
1266+ - libboost-system-dev
1267+ - libdbus-1-dev
1268+ - libgoogle-glog-dev
1269+ - libgtest-dev
1270+ - libiw-dev
1271+ - libjson-c-dev
1272+ - libnet-cpp-dev
1273+ - libprocess-cpp-dev
1274+ - libtrust-store-dev
1275+ - libproperties-cpp-dev
1276+ - trust-store-bin
1277+ glue:
1278+ plugin: copy
1279+ after:
1280+ - location-service
1281+ files:
1282+ stage/bin/ubuntu-location-serviced: bin/ubuntu-location-serviced
1283+ stage/bin/ubuntu-location-service-providerd: bin/ubuntu-location-service-providerd
1284
1285=== modified file 'src/location_service/com/ubuntu/location/CMakeLists.txt'
1286--- src/location_service/com/ubuntu/location/CMakeLists.txt 2015-04-23 14:48:44 +0000
1287+++ src/location_service/com/ubuntu/location/CMakeLists.txt 2016-01-25 14:24:35 +0000
1288@@ -38,6 +38,7 @@
1289 service/harvester.cpp
1290 service/demultiplexing_reporter.h
1291 service/demultiplexing_reporter.cpp
1292+ service/runtime.cpp
1293 service/runtime_tests.h
1294 service/runtime_tests.cpp
1295 service/trust_store_permission_manager.cpp
1296
1297=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp'
1298--- src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp 2015-05-28 10:57:24 +0000
1299+++ src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.cpp 2016-01-25 14:24:35 +0000
1300@@ -123,7 +123,14 @@
1301 const org::freedesktop::NetworkManager::Device& device,
1302 const org::freedesktop::NetworkManager::AccessPoint& ap)
1303 : device_(device),
1304- access_point_(ap)
1305+ access_point_(ap),
1306+ connections
1307+ {
1308+ access_point_.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
1309+ {
1310+ on_access_point_properties_changed(dict);
1311+ })
1312+ }
1313 {
1314 last_seen_ = translate_time_stamp(access_point_.last_seen->get());
1315
1316@@ -138,12 +145,11 @@
1317 {
1318 static_cast<int>(access_point_.strength->get())
1319 };
1320+}
1321
1322- // Wire up all the connections
1323- access_point_.properties_changed->connect([this](const std::map<std::string, core::dbus::types::Variant>& dict)
1324- {
1325- on_access_point_properties_changed(dict);
1326- });
1327+detail::CachedWirelessNetwork::~CachedWirelessNetwork()
1328+{
1329+ access_point_.properties_changed->disconnect(connections.ap_properties_changed);
1330 }
1331
1332 void detail::CachedWirelessNetwork::on_access_point_properties_changed(const std::map<std::string, core::dbus::types::Variant>& dict)
1333
1334=== modified file 'src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h'
1335--- src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h 2014-08-14 20:25:22 +0000
1336+++ src/location_service/com/ubuntu/location/connectivity/cached_wireless_network.h 2016-01-25 14:24:35 +0000
1337@@ -41,6 +41,8 @@
1338 const org::freedesktop::NetworkManager::Device& device,
1339 const org::freedesktop::NetworkManager::AccessPoint& ap);
1340
1341+ ~CachedWirelessNetwork();
1342+
1343 // Timestamp when the network became visible.
1344 const core::Property<std::chrono::system_clock::time_point>& last_seen() const override;
1345
1346@@ -67,6 +69,16 @@
1347 // The actual access point stub.
1348 org::freedesktop::NetworkManager::AccessPoint access_point_;
1349
1350+ // Encapsulates all event connections that have to be cut on destruction.
1351+ struct
1352+ {
1353+ core::dbus::Signal
1354+ <
1355+ org::freedesktop::NetworkManager::AccessPoint::PropertiesChanged,
1356+ org::freedesktop::NetworkManager::AccessPoint::PropertiesChanged::ArgumentType
1357+ >::SubscriptionToken ap_properties_changed;
1358+ } connections;
1359+
1360 core::Property<std::chrono::system_clock::time_point> last_seen_;
1361 core::Property<std::string> bssid_;
1362 core::Property<std::string> ssid_;
1363
1364=== modified file 'src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp'
1365--- src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2015-05-27 18:40:37 +0000
1366+++ src/location_service/com/ubuntu/location/connectivity/ofono_nm_connectivity_manager.cpp 2016-01-25 14:24:35 +0000
1367@@ -595,7 +595,7 @@
1368
1369 xdg::NetworkManager::AccessPoint ap
1370 {
1371- network_manager->service->add_object_for_path(ap_path)
1372+ network_manager->service->object_for_path(ap_path)
1373 };
1374
1375 auto wifi = std::make_shared<detail::CachedWirelessNetwork>(itd->second, ap);
1376
1377=== modified file 'src/location_service/com/ubuntu/location/engine.cpp'
1378--- src/location_service/com/ubuntu/location/engine.cpp 2015-04-23 14:48:44 +0000
1379+++ src/location_service/com/ubuntu/location/engine.cpp 2016-01-25 14:24:35 +0000
1380@@ -169,19 +169,28 @@
1381
1382 // We wire up changes in the engine's configuration to the respective slots
1383 // of the provider.
1384- auto cp = updates.reference_location.changed().connect([provider](const cul::Update<cul::Position>& pos)
1385- {
1386- provider->on_reference_location_updated(pos);
1387- });
1388-
1389- auto cv = updates.reference_velocity.changed().connect([provider](const cul::Update<cul::Velocity>& velocity)
1390- {
1391- provider->on_reference_velocity_updated(velocity);
1392- });
1393-
1394- auto ch = updates.reference_heading.changed().connect([provider](const cul::Update<cul::Heading>& heading)
1395- {
1396- provider->on_reference_heading_updated(heading);
1397+ auto cp = updates.last_known_location.changed().connect([provider](const cul::Optional<cul::Update<cul::Position>>& pos)
1398+ {
1399+ if (pos)
1400+ {
1401+ provider->on_reference_location_updated(pos.get());
1402+ }
1403+ });
1404+
1405+ auto cv = updates.last_known_velocity.changed().connect([provider](const cul::Optional<cul::Update<cul::Velocity>>& velocity)
1406+ {
1407+ if (velocity)
1408+ {
1409+ provider->on_reference_velocity_updated(velocity.get());
1410+ }
1411+ });
1412+
1413+ auto ch = updates.last_known_heading.changed().connect([provider](const cul::Optional<cul::Update<cul::Heading>>& heading)
1414+ {
1415+ if (heading)
1416+ {
1417+ provider->on_reference_heading_updated(heading.get());
1418+ }
1419 });
1420
1421 auto cr = configuration.wifi_and_cell_id_reporting_state.changed().connect([provider](cul::WifiAndCellIdReportingState state)
1422@@ -207,7 +216,7 @@
1423 // We should come up with a better heuristic here.
1424 auto cpr = provider->updates().position.connect([this](const cul::Update<cul::Position>& src)
1425 {
1426- updates.reference_location = update_policy->verify_update(src);
1427+ updates.last_known_location = update_policy->verify_update(src);
1428 });
1429
1430 std::lock_guard<std::mutex> lg(guard);
1431
1432=== modified file 'src/location_service/com/ubuntu/location/engine.h'
1433--- src/location_service/com/ubuntu/location/engine.h 2015-04-23 14:48:44 +0000
1434+++ src/location_service/com/ubuntu/location/engine.h 2016-01-25 14:24:35 +0000
1435@@ -127,11 +127,11 @@
1436 struct Updates
1437 {
1438 /** The current best known reference location */
1439- core::Property<Update<Position>> reference_location{};
1440+ core::Property<Optional<Update<Position>>> last_known_location{};
1441 /** The current best known velocity estimate. */
1442- core::Property<Update<Velocity>> reference_velocity{};
1443+ core::Property<Optional<Update<Velocity>>> last_known_velocity{};
1444 /** The current best known heading estimate. */
1445- core::Property<Update<Heading>> reference_heading{};
1446+ core::Property<Optional<Update<Heading>>> last_known_heading{};
1447 /** The current set of visible SpaceVehicles. */
1448 core::Property<std::map<SpaceVehicle::Key, SpaceVehicle>> visible_space_vehicles{};
1449 };
1450
1451=== modified file 'src/location_service/com/ubuntu/location/provider_factory.cpp'
1452--- src/location_service/com/ubuntu/location/provider_factory.cpp 2014-10-27 21:58:16 +0000
1453+++ src/location_service/com/ubuntu/location/provider_factory.cpp 2016-01-25 14:24:35 +0000
1454@@ -52,6 +52,20 @@
1455 return cul::Provider::Ptr{factory_store.at(undecorated_name)(config)};
1456 }
1457
1458+void cul::ProviderFactory::create_provider_for_name_with_config(
1459+ const std::string& name,
1460+ const cul::ProviderFactory::Configuration& config,
1461+ const std::function<void(Provider::Ptr)>& cb)
1462+{
1463+ auto undecorated_name = name.substr(0, name.find("@"));
1464+
1465+ std::lock_guard<std::mutex> lg(guard);
1466+ if (factory_store.count(undecorated_name) == 0)
1467+ return;
1468+
1469+ cb(cul::Provider::Ptr{factory_store.at(undecorated_name)(config)});
1470+}
1471+
1472 void cul::ProviderFactory::enumerate(
1473 const std::function<void(const std::string&, const cul::ProviderFactory::Factory&)>& enumerator)
1474 {
1475
1476=== modified file 'src/location_service/com/ubuntu/location/providers/config.cpp'
1477--- src/location_service/com/ubuntu/location/providers/config.cpp 2014-09-15 08:58:50 +0000
1478+++ src/location_service/com/ubuntu/location/providers/config.cpp 2016-01-25 14:24:35 +0000
1479@@ -19,6 +19,7 @@
1480 #include <com/ubuntu/location/provider_factory.h>
1481
1482 #include "dummy/provider.h"
1483+#include "dummy/delayed_provider.h"
1484
1485 #include <map>
1486
1487@@ -41,6 +42,12 @@
1488 com::ubuntu::location::providers::dummy::Provider::create_instance
1489 };
1490
1491+static FactoryInjector dummy_delayed_injector
1492+{
1493+ "dummy::DelayedProvider",
1494+ com::ubuntu::location::providers::dummy::DelayedProvider::create_instance
1495+};
1496+
1497 #include <com/ubuntu/location/providers/remote/provider.h>
1498 static FactoryInjector remote_injector
1499 {
1500
1501=== modified file 'src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt'
1502--- src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt 2014-02-07 17:16:49 +0000
1503+++ src/location_service/com/ubuntu/location/providers/dummy/CMakeLists.txt 2016-01-25 14:24:35 +0000
1504@@ -2,7 +2,9 @@
1505 dummy
1506
1507 provider.h
1508- provider.cpp)
1509+ provider.cpp
1510+ delayed_provider.h
1511+ delayed_provider.cpp)
1512
1513 set(
1514 ENABLED_PROVIDER_TARGETS
1515
1516=== added file 'src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp'
1517--- src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp 1970-01-01 00:00:00 +0000
1518+++ src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.cpp 2016-01-25 14:24:35 +0000
1519@@ -0,0 +1,42 @@
1520+/*
1521+ * Copyright © 2015 Canonical Ltd.
1522+ *
1523+ * This program is free software: you can redistribute it and/or modify it
1524+ * under the terms of the GNU Lesser General Public License version 3,
1525+ * as published by the Free Software Foundation.
1526+ *
1527+ * This program is distributed in the hope that it will be useful,
1528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1530+ * GNU Lesser General Public License for more details.
1531+ *
1532+ * You should have received a copy of the GNU Lesser General Public License
1533+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1534+ *
1535+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com>
1536+ */
1537+
1538+#include <com/ubuntu/location/logging.h>
1539+
1540+#include <chrono>
1541+#include <thread>
1542+
1543+#include "delayed_provider.h"
1544+
1545+namespace location = com::ubuntu::location;
1546+namespace dummy = com::ubuntu::location::providers::dummy;
1547+
1548+std::string dummy::DelayedProvider::class_name()
1549+{
1550+ return "dummy::DelayedProvider";
1551+}
1552+
1553+location::Provider::Ptr dummy::DelayedProvider::create_instance(const ProviderFactory::Configuration& config)
1554+{
1555+ int delay = config.get(dummy::DelayConfiguration::Keys::delay, 0);
1556+ VLOG(1) << __PRETTY_FUNCTION__ << ": delay for " << delay << "ms";
1557+
1558+ std::this_thread::sleep_for(std::chrono::milliseconds{delay});
1559+
1560+ return dummy::Provider::create_instance(config);
1561+}
1562
1563=== added file 'src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h'
1564--- src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h 1970-01-01 00:00:00 +0000
1565+++ src/location_service/com/ubuntu/location/providers/dummy/delayed_provider.h 2016-01-25 14:24:35 +0000
1566@@ -0,0 +1,62 @@
1567+/*
1568+ * Copyright © 2015 Canonical Ltd.
1569+ *
1570+ * This program is free software: you can redistribute it and/or modify it
1571+ * under the terms of the GNU Lesser General Public License version 3,
1572+ * as published by the Free Software Foundation.
1573+ *
1574+ * This program is distributed in the hope that it will be useful,
1575+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1576+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1577+ * GNU Lesser General Public License for more details.
1578+ *
1579+ * You should have received a copy of the GNU Lesser General Public License
1580+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1581+ *
1582+ * Authored by: Scott Sweeny <scott.sweeny@canonical.com>
1583+ */
1584+
1585+#ifndef LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1586+#define LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1587+
1588+#include "provider.h"
1589+
1590+namespace com
1591+{
1592+namespace ubuntu
1593+{
1594+namespace location
1595+{
1596+namespace providers
1597+{
1598+namespace dummy
1599+{
1600+ struct DelayConfiguration
1601+ {
1602+ struct Keys
1603+ {
1604+ static constexpr const char* delay
1605+ {
1606+ "DelayInMs"
1607+ };
1608+ };
1609+ };
1610+
1611+class DelayedProvider : public Provider
1612+{
1613+ public:
1614+ // For integration with the Provider factory
1615+ static std::string class_name();
1616+ // Waits for "DelayInMs" from the provided property bundle then
1617+ // instantiates a new provider instance, populating the configuration object
1618+ // from the provided property bundle.
1619+ static DelayedProvider::Ptr create_instance(const ProviderFactory::Configuration&);
1620+ // Creates a new provider instance from the given configuration.
1621+ DelayedProvider(const Configuration config = Configuration{});
1622+};
1623+}
1624+}
1625+}
1626+}
1627+}
1628+#endif // LOCATION_SERVICE_COM_UBUNTU_LOCATION_PROVIDERS_DUMMY_DELAYED_PROVIDER_H_
1629
1630=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp'
1631--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2014-10-27 21:58:16 +0000
1632+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.cpp 2016-01-25 14:24:35 +0000
1633@@ -66,8 +66,6 @@
1634 if (config.count("XTRA_SERVER_3") > 0)
1635 result.xtra_hosts.push_back(config.get<std::string>("XTRA_SERVER_3"));
1636
1637- result.timeout = std::chrono::milliseconds{1500};
1638-
1639 return result;
1640 }
1641
1642@@ -333,14 +331,14 @@
1643 } else
1644 {
1645 auto now = location::Clock::now().time_since_epoch();
1646- auto thiz = static_cast<android::HardwareAbstractionLayer*>(context);
1647+ auto ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(now);
1648
1649 static const int zero_uncertainty = 0;
1650
1651 u_hardware_gps_inject_time(
1652 thiz->impl.gps_handle,
1653- now.count(),
1654- now.count(),
1655+ ms_since_epoch.count(),
1656+ ms_since_epoch.count(),
1657 zero_uncertainty);
1658 }
1659 }
1660
1661=== modified file 'src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h'
1662--- src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2015-04-22 13:30:04 +0000
1663+++ src/location_service/com/ubuntu/location/providers/gps/android_hardware_abstraction_layer.h 2016-01-25 14:24:35 +0000
1664@@ -49,7 +49,7 @@
1665 /** @brief Timeout on gps xtra download operations. */
1666 std::chrono::milliseconds timeout
1667 {
1668- 5000
1669+ 30000
1670 };
1671
1672 /** Set of hosts serving GPS xtra data. */
1673
1674=== modified file 'src/location_service/com/ubuntu/location/providers/remote/provider.cpp'
1675--- src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2015-04-14 18:54:00 +0000
1676+++ src/location_service/com/ubuntu/location/providers/remote/provider.cpp 2016-01-25 14:24:35 +0000
1677@@ -23,6 +23,7 @@
1678 #include <com/ubuntu/location/logging.h>
1679
1680 #include <core/dbus/object.h>
1681+#include <core/dbus/service_watcher.h>
1682 #include <core/dbus/signal.h>
1683 #include <core/dbus/asio/executor.h>
1684
1685@@ -191,6 +192,28 @@
1686 auto service = dbus::Service::use_service(bus, name);
1687 auto object = service->object_for_path(path);
1688
1689+ // Check if the service has come up
1690+ if (!bus->has_owner_for_name(name)) {
1691+ // If it hasn't wait for it to come up
1692+ bool valid = false;
1693+ std::mutex guard;
1694+ std::condition_variable cv;
1695+ dbus::DBus daemon(bus);
1696+ dbus::ServiceWatcher::Ptr service_watcher(
1697+ daemon.make_service_watcher(name, dbus::DBus::WatchMode::registration));
1698+
1699+ service_watcher->service_registered().connect([&valid, &guard, &cv]()
1700+ {
1701+ std::unique_lock<std::mutex> ul(guard);
1702+ valid = true;
1703+ cv.notify_all();
1704+ });
1705+
1706+ std::unique_lock<std::mutex> ul(guard);
1707+ if (not cv.wait_for(ul, std::chrono::seconds{30}, [&valid]() { return valid; }))
1708+ throw std::runtime_error("Remote service failed to start");
1709+ }
1710+
1711 return create_instance_with_config(remote::stub::Configuration{object});
1712 }
1713
1714
1715=== modified file 'src/location_service/com/ubuntu/location/service/daemon.cpp'
1716--- src/location_service/com/ubuntu/location/service/daemon.cpp 2015-04-16 10:03:29 +0000
1717+++ src/location_service/com/ubuntu/location/service/daemon.cpp 2016-01-25 14:24:35 +0000
1718@@ -20,6 +20,9 @@
1719 #include <com/ubuntu/location/boost_ptree_settings.h>
1720 #include <com/ubuntu/location/provider_factory.h>
1721
1722+#include <com/ubuntu/location/logging.h>
1723+#include <com/ubuntu/location/connectivity/dummy_connectivity_manager.h>
1724+
1725 #include <com/ubuntu/location/service/default_configuration.h>
1726 #include <com/ubuntu/location/service/demultiplexing_reporter.h>
1727 #include <com/ubuntu/location/service/ichnaea_reporter.h>
1728@@ -30,6 +33,7 @@
1729
1730 #include "program_options.h"
1731 #include "daemon.h"
1732+#include "runtime.h"
1733
1734 #include <core/dbus/announcer.h>
1735 #include <core/dbus/resolver.h>
1736@@ -37,6 +41,8 @@
1737
1738 #include <core/posix/signal.h>
1739
1740+#include <boost/asio.hpp>
1741+
1742 #include <system_error>
1743 #include <thread>
1744
1745@@ -175,116 +181,55 @@
1746 trap->stop();
1747 });
1748
1749- const location::Configuration empty_provider_configuration;
1750-
1751- std::set<location::Provider::Ptr> instantiated_providers;
1752-
1753+ auto runtime = location::service::Runtime::create(4);
1754+
1755+ location::service::DefaultConfiguration dc;
1756+ auto engine = dc.the_engine(std::set<location::Provider::Ptr>{}, dc.the_provider_selection_policy(), config.settings);
1757 for (const std::string& provider : config.providers)
1758 {
1759 std::cout << "Instantiating and configuring: " << provider << std::endl;
1760
1761 try
1762 {
1763- auto p = location::ProviderFactory::instance().create_provider_for_name_with_config(
1764- provider,
1765- config.provider_options.count(provider) > 0 ?
1766- config.provider_options.at(provider) : empty_provider_configuration);
1767-
1768- if (p)
1769- instantiated_providers.insert(p);
1770- else
1771- throw std::runtime_error("Problem instantiating provider");
1772-
1773+ auto result = std::async(std::launch::async, [provider, config, engine] {
1774+ return location::ProviderFactory::instance().create_provider_for_name_with_config(
1775+ provider,
1776+ config.provider_options.count(provider) > 0 ?
1777+ config.provider_options.at(provider) : location::Configuration {},
1778+ [engine](Provider::Ptr provider)
1779+ {
1780+ engine->add_provider(provider);
1781+ }
1782+ );
1783+ });
1784 } catch(const std::runtime_error& e)
1785 {
1786 std::cerr << "Issue instantiating provider: " << e.what() << std::endl;
1787 }
1788 }
1789
1790- config.incoming->install_executor(dbus::asio::make_executor(config.incoming));
1791- config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing));
1792+ config.incoming->install_executor(dbus::asio::make_executor(config.incoming, runtime->service()));
1793+ config.outgoing->install_executor(dbus::asio::make_executor(config.outgoing, runtime->service()));
1794
1795- location::service::DefaultConfiguration dc;
1796+ runtime->start();
1797
1798 location::service::Implementation::Configuration configuration
1799 {
1800 config.incoming,
1801 config.outgoing,
1802- dc.the_engine(instantiated_providers, dc.the_provider_selection_policy(), config.settings),
1803+ engine,
1804 dc.the_permission_manager(config.outgoing),
1805 location::service::Harvester::Configuration
1806 {
1807- location::connectivity::platform_default_manager(),
1808- // We submit location/wifi/cell measurements to both
1809- // Mozilla's location service and to Ubuntu's own instance.
1810- std::make_shared<service::DemultiplexingReporter>(
1811- std::initializer_list<service::Harvester::Reporter::Ptr>
1812- {
1813- std::make_shared<service::ichnaea::Reporter>(
1814- service::ichnaea::Reporter::Configuration
1815- {
1816- "https://location.services.mozilla.com",
1817- "UbuntuLocationService",
1818- "UbuntuLocationService"
1819- }
1820- ),
1821- std::make_shared<service::ichnaea::Reporter>(
1822- service::ichnaea::Reporter::Configuration
1823- {
1824- "https://162.213.35.107",
1825- "UbuntuLocationService",
1826- "UbuntuLocationService"
1827- }
1828- )
1829- })
1830+ std::make_shared<dummy::ConnectivityManager>(),
1831+ std::make_shared<NullReporter>()
1832 }
1833 };
1834
1835 auto location_service = std::make_shared<location::service::Implementation>(configuration);
1836- // We need to ensure that any exception raised by the executor does not crash the app
1837- // and also gets logged.
1838- auto execute = [] (std::shared_ptr<core::dbus::Bus> bus) {
1839- while(true)
1840- {
1841- try
1842- {
1843- VLOG(10) << "Starting a bus executor";
1844- bus->run();
1845- break; // run() exited normally
1846- }
1847- catch (const std::exception& e)
1848- {
1849- LOG(WARNING) << e.what();
1850- }
1851- catch (...)
1852- {
1853- LOG(WARNING) << "Unexpected exception was raised by the bus executor";
1854- }
1855- }
1856- };
1857-
1858- std::thread t1{execute, config.incoming};
1859- std::thread t2{execute, config.incoming};
1860- std::thread t3{execute, config.incoming};
1861- std::thread t4{execute, config.outgoing};
1862
1863 trap->run();
1864
1865- config.incoming->stop();
1866- config.outgoing->stop();
1867-
1868- if (t1.joinable())
1869- t1.join();
1870-
1871- if (t2.joinable())
1872- t2.join();
1873-
1874- if (t3.joinable())
1875- t3.join();
1876-
1877- if (t4.joinable())
1878- t4.join();
1879-
1880 return EXIT_SUCCESS;
1881 }
1882
1883
1884=== modified file 'src/location_service/com/ubuntu/location/service/implementation.cpp'
1885--- src/location_service/com/ubuntu/location/service/implementation.cpp 2014-08-13 13:08:22 +0000
1886+++ src/location_service/com/ubuntu/location/service/implementation.cpp 2016-01-25 14:24:35 +0000
1887@@ -113,10 +113,13 @@
1888 {
1889 visible_space_vehicles() = svs;
1890 }),
1891- configuration.engine->updates.reference_location.changed().connect(
1892- [this](const cul::Update<cul::Position>& update)
1893+ configuration.engine->updates.last_known_location.changed().connect(
1894+ [this](const cul::Optional<cul::Update<cul::Position>>& update)
1895 {
1896- harvester.report_position_update(update);
1897+ if (update)
1898+ {
1899+ harvester.report_position_update(update.get());
1900+ }
1901 })
1902 }
1903 {
1904@@ -149,5 +152,23 @@
1905 new ProxyProvider{provider_selection}
1906 };
1907
1908- return session::Interface::Ptr{new culs::session::Implementation(proxy_provider)};
1909+ session::Interface::Ptr session_iface{new session::Implementation(proxy_provider)};
1910+ std::weak_ptr<session::Interface> session_weak{session_iface};
1911+ session_iface->updates().position_status.changed().connect([this, session_weak](const session::Interface::Updates::Status& status)
1912+ {
1913+ cul::Optional<cul::Update<cul::Position>> last_known_position = configuration.engine->updates.last_known_location.get();
1914+ bool has_last_known_position = last_known_position ? true : false;
1915+ bool is_session_enabled = status == culs::session::Interface::Updates::Status::enabled;
1916+ bool is_session_on_or_active = configuration.engine->configuration.engine_state != Engine::Status::off;
1917+
1918+ if (has_last_known_position && is_session_enabled && is_session_on_or_active)
1919+ {
1920+ // Immediately send the last known position to the client
1921+ if (auto session_iface = session_weak.lock())
1922+ {
1923+ session_iface->updates().position = last_known_position.get();
1924+ }
1925+ }
1926+ });
1927+ return session_iface;
1928 }
1929
1930=== modified file 'src/location_service/com/ubuntu/location/service/provider_daemon.cpp'
1931--- src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2014-10-27 21:58:16 +0000
1932+++ src/location_service/com/ubuntu/location/service/provider_daemon.cpp 2016-01-25 14:24:35 +0000
1933@@ -25,6 +25,7 @@
1934
1935 #include <com/ubuntu/location/service/configuration.h>
1936 #include <com/ubuntu/location/service/program_options.h>
1937+#include <com/ubuntu/location/service/runtime.h>
1938
1939 #include <core/dbus/asio/executor.h>
1940
1941@@ -65,7 +66,6 @@
1942 location::service::ProviderDaemon::Configuration result;
1943
1944 result.connection = factory(mutable_daemon_options().bus());
1945- result.connection->install_executor(core::dbus::asio::make_executor(result.connection));
1946
1947 auto service = core::dbus::Service::add_service(
1948 result.connection,
1949@@ -108,7 +108,15 @@
1950 return result;
1951 }
1952
1953-int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& configuration)
1954+namespace
1955+{
1956+std::shared_ptr<location::service::Runtime> runtime()
1957+{
1958+ static const auto inst = location::service::Runtime::create(2);
1959+ return inst;
1960+}
1961+}
1962+int location::service::ProviderDaemon::main(const location::service::ProviderDaemon::Configuration& config)
1963 {
1964 auto trap = core::posix::trap_signals_for_all_subsequent_threads(
1965 {
1966@@ -121,27 +129,20 @@
1967 trap->stop();
1968 });
1969
1970- std::thread worker
1971- {
1972- [configuration]()
1973- {
1974- configuration.connection->run();
1975- }
1976- };
1977+ config.connection->install_executor(core::dbus::asio::make_executor(config.connection, runtime()->service()));
1978
1979 auto skeleton = location::providers::remote::skeleton::create_with_configuration(location::providers::remote::skeleton::Configuration
1980 {
1981- configuration.object,
1982- configuration.connection,
1983- configuration.provider
1984+ config.object,
1985+ config.connection,
1986+ config.provider
1987 });
1988
1989+ runtime()->start();
1990+
1991 trap->run();
1992
1993- configuration.connection->stop();
1994-
1995- if (worker.joinable())
1996- worker.join();
1997+ config.connection->stop();
1998
1999 return EXIT_SUCCESS;
2000 }
2001
2002=== added file 'src/location_service/com/ubuntu/location/service/runtime.cpp'
2003--- src/location_service/com/ubuntu/location/service/runtime.cpp 1970-01-01 00:00:00 +0000
2004+++ src/location_service/com/ubuntu/location/service/runtime.cpp 2016-01-25 14:24:35 +0000
2005@@ -0,0 +1,109 @@
2006+/*
2007+ * Copyright © 2015 Canonical Ltd.
2008+ *
2009+ * This program is free software: you can redistribute it and/or modify it
2010+ * under the terms of the GNU Lesser General Public License version 3,
2011+ * as published by the Free Software Foundation.
2012+ *
2013+ * This program is distributed in the hope that it will be useful,
2014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2015+ * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the
2016+ * GNU Lesser General Public License for more details.
2017+ *
2018+ * You should have received a copy of the GNU Lesser General Public License
2019+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2020+ *
2021+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2022+ */
2023+#include <com/ubuntu/location/service/runtime.h>
2024+
2025+#include <com/ubuntu/location/logging.h>
2026+
2027+namespace culs = com::ubuntu::location::service;
2028+
2029+namespace
2030+{
2031+// exception_safe_run runs service, catching all exceptions and
2032+// restarting operation until an explicit shutdown has been requested.
2033+//
2034+// TODO(tvoss): Catching all exceptions is risky as they might signal unrecoverable
2035+// errors. We should enable calling code to decide whether an exception should be considered
2036+// fatal or not.
2037+void exception_safe_run(boost::asio::io_service& service)
2038+{
2039+ while (true)
2040+ {
2041+ try
2042+ {
2043+ service.run();
2044+ // a clean return from run only happens in case of
2045+ // stop() being called (we are keeping the service alive with
2046+ // a service::work instance).
2047+ break;
2048+ }
2049+ catch (const std::exception& e)
2050+ {
2051+ LOG(WARNING) << e.what();
2052+ }
2053+ catch (...)
2054+ {
2055+ LOG(WARNING) << "Unknown exception caught while executing boost::asio::io_service";
2056+ }
2057+ }
2058+}
2059+}
2060+
2061+std::shared_ptr<culs::Runtime> culs::Runtime::create(std::uint32_t pool_size)
2062+{
2063+ return std::shared_ptr<culs::Runtime>(new culs::Runtime(pool_size));
2064+}
2065+
2066+culs::Runtime::Runtime(std::uint32_t pool_size)
2067+ : pool_size_{pool_size},
2068+ service_{pool_size_},
2069+ strand_{service_},
2070+ keep_alive_{service_}
2071+{
2072+}
2073+
2074+culs::Runtime::~Runtime()
2075+{
2076+ try
2077+ {
2078+ stop();
2079+ } catch(...)
2080+ {
2081+ // Dropping all exceptions to satisfy the nothrow guarantee.
2082+ }
2083+}
2084+
2085+void culs::Runtime::start()
2086+{
2087+ for (unsigned int i = 0; i < pool_size_; i++)
2088+ workers_.push_back(std::thread{exception_safe_run, std::ref(service_)});
2089+}
2090+
2091+void culs::Runtime::stop()
2092+{
2093+ service_.stop();
2094+
2095+ for (auto& worker : workers_)
2096+ if (worker.joinable())
2097+ worker.join();
2098+}
2099+
2100+std::function<void(std::function<void()>)> culs::Runtime::to_dispatcher_functional()
2101+{
2102+ // We have to make sure that we stay alive for as long as
2103+ // calling code requires the dispatcher to work.
2104+ auto sp = shared_from_this();
2105+ return [sp](std::function<void()> task)
2106+ {
2107+ sp->strand_.post(task);
2108+ };
2109+}
2110+
2111+boost::asio::io_service& culs::Runtime::service()
2112+{
2113+ return service_;
2114+}
2115
2116=== added file 'src/location_service/com/ubuntu/location/service/runtime.h'
2117--- src/location_service/com/ubuntu/location/service/runtime.h 1970-01-01 00:00:00 +0000
2118+++ src/location_service/com/ubuntu/location/service/runtime.h 2016-01-25 14:24:35 +0000
2119@@ -0,0 +1,90 @@
2120+/*
2121+ * Copyright © 2015 Canonical Ltd.
2122+ *
2123+ * This program is free software: you can redistribute it and/or modify it
2124+ * under the terms of the GNU Lesser General Public License version 3,
2125+ * as published by the Free Software Foundation.
2126+ *
2127+ * This program is distributed in the hope that it will be useful,
2128+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2129+ * MERCHANTABILITY or FITNESS FOR A PARTIlocationAR PURPOSE. See the
2130+ * GNU Lesser General Public License for more details.
2131+ *
2132+ * You should have received a copy of the GNU Lesser General Public License
2133+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2134+ *
2135+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2136+ */
2137+#ifndef COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
2138+#define COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
2139+
2140+#include <boost/asio.hpp>
2141+
2142+#include <functional>
2143+#include <memory>
2144+#include <thread>
2145+#include <vector>
2146+
2147+#include <cstdint>
2148+
2149+namespace com
2150+{
2151+namespace ubuntu
2152+{
2153+namespace location
2154+{
2155+namespace service
2156+{
2157+// We bundle our "global" runtime dependencies here, specifically
2158+// a dispatcher to decouple multiple in-process providers from one
2159+// another , forcing execution to a well known set of threads.
2160+class Runtime : public std::enable_shared_from_this<Runtime>
2161+{
2162+public:
2163+ // Our default concurrency setup.
2164+ static constexpr const std::uint32_t worker_threads = 2;
2165+
2166+ // create returns a Runtime instance with pool_size worker threads
2167+ // executing the underlying service.
2168+ static std::shared_ptr<Runtime> create(std::uint32_t pool_size = worker_threads);
2169+
2170+ Runtime(const Runtime&) = delete;
2171+ Runtime(Runtime&&) = delete;
2172+ // Tears down the runtime, stopping all worker threads.
2173+ ~Runtime() noexcept(true);
2174+ Runtime& operator=(const Runtime&) = delete;
2175+ Runtime& operator=(Runtime&&) = delete;
2176+
2177+ // start executes the underlying io_service on a thread pool with
2178+ // the size configured at creation time.
2179+ void start();
2180+
2181+ // stop cleanly shuts down a Runtime instance,
2182+ // joining all worker threads.
2183+ void stop();
2184+
2185+ // to_dispatcher_functional returns a function for integration
2186+ // with components that expect a dispatcher for operation.
2187+ std::function<void(std::function<void()>)> to_dispatcher_functional();
2188+
2189+ // service returns the underlying boost::asio::io_service that is executed
2190+ // by the Runtime.
2191+ boost::asio::io_service& service();
2192+
2193+private:
2194+ // Runtime constructs a new instance, firing up pool_size
2195+ // worker threads.
2196+ Runtime(std::uint32_t pool_size);
2197+
2198+ std::uint32_t pool_size_;
2199+ boost::asio::io_service service_;
2200+ boost::asio::io_service::strand strand_;
2201+ boost::asio::io_service::work keep_alive_;
2202+ std::vector<std::thread> workers_;
2203+};
2204+}
2205+}
2206+}
2207+}
2208+
2209+#endif // COM_UBUNTU_LOCATION_SERVICE_RUNTIME_H_
2210
2211=== modified file 'src/location_service/com/ubuntu/location/service/session/skeleton.cpp'
2212--- src/location_service/com/ubuntu/location/service/session/skeleton.cpp 2014-08-14 20:31:09 +0000
2213+++ src/location_service/com/ubuntu/location/service/session/skeleton.cpp 2016-01-25 14:24:35 +0000
2214@@ -283,7 +283,13 @@
2215 VLOG(10) << __PRETTY_FUNCTION__;
2216 try
2217 {
2218- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdatePosition, void>(position);
2219+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdatePosition, void>([](const core::dbus::Result<void>& result)
2220+ {
2221+ if (result.is_error())
2222+ {
2223+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
2224+ }
2225+ }, position);
2226 } catch(const std::exception&)
2227 {
2228 // We consider the session to be dead once we hit an exception here.
2229@@ -300,7 +306,13 @@
2230 VLOG(10) << __PRETTY_FUNCTION__;
2231 try
2232 {
2233- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdateHeading, void>(heading);
2234+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdateHeading, void>([](const core::dbus::Result<void>& result)
2235+ {
2236+ if (result.is_error())
2237+ {
2238+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
2239+ }
2240+ }, heading);
2241 } catch(const std::exception&)
2242 {
2243 // We consider the session to be dead once we hit an exception here.
2244@@ -317,7 +329,13 @@
2245 VLOG(10) << __PRETTY_FUNCTION__;
2246 try
2247 {
2248- configuration.remote.object->invoke_method_asynchronously<culs::session::Interface::UpdateVelocity, void>(velocity);
2249+ configuration.remote.object->invoke_method_asynchronously_with_callback<culs::session::Interface::UpdateVelocity, void>([](const core::dbus::Result<void>& result)
2250+ {
2251+ if (result.is_error())
2252+ {
2253+ LOG(INFO) << "Failed to communicate position update to client: " << result.error().print();
2254+ }
2255+ }, velocity);
2256 } catch(const std::exception&)
2257 {
2258 // We consider the session to be dead once we hit an exception here.
2259
2260=== modified file 'src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp'
2261--- src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp 2014-09-19 14:36:51 +0000
2262+++ src/location_service/com/ubuntu/location/service/trust_store_permission_manager.cpp 2016-01-25 14:24:35 +0000
2263@@ -146,7 +146,7 @@
2264 return service::PermissionManager::Result::rejected;
2265 }
2266
2267- std::string description = i18n::tr("%1% wants to access your current location.");
2268+ std::string description = i18n::tr("wants to access your current location.");
2269
2270 core::trust::Agent::RequestParameters params
2271 {
2272
2273=== modified file 'src/location_service/com/ubuntu/location/time_based_update_policy.cpp'
2274--- src/location_service/com/ubuntu/location/time_based_update_policy.cpp 2015-04-23 21:30:04 +0000
2275+++ src/location_service/com/ubuntu/location/time_based_update_policy.cpp 2016-01-25 14:24:35 +0000
2276@@ -53,8 +53,9 @@
2277 {
2278 // if the update has happened within a reasonable amount of time we will just use it if it is more accurate
2279 // that the previous one.
2280- use_new_update = last_position_update.value.accuracy.horizontal && update.value.accuracy.horizontal
2281- && *last_position_update.value.accuracy.horizontal >= *update.value.accuracy.horizontal;
2282+ use_new_update = !last_position_update.value.accuracy.horizontal ||
2283+ (update.value.accuracy.horizontal
2284+ && *last_position_update.value.accuracy.horizontal >= *update.value.accuracy.horizontal);
2285 }
2286
2287 if (use_new_update)
2288@@ -118,4 +119,4 @@
2289
2290 }
2291 }
2292-}
2293\ No newline at end of file
2294+}
2295
2296=== modified file 'tests/CMakeLists.txt'
2297--- tests/CMakeLists.txt 2015-04-23 17:04:09 +0000
2298+++ tests/CMakeLists.txt 2016-01-25 14:24:35 +0000
2299@@ -92,6 +92,7 @@
2300 LOCATION_SERVICE_ADD_TEST(provider_test provider_test.cpp)
2301 LOCATION_SERVICE_ADD_TEST(wgs84_test wgs84_test.cpp)
2302 LOCATION_SERVICE_ADD_TEST(trust_store_permission_manager_test trust_store_permission_manager_test.cpp)
2303+LOCATION_SERVICE_ADD_TEST(runtime_test runtime_test.cpp)
2304
2305 # Provider-specific test-cases go here.
2306 if (LOCATION_SERVICE_ENABLE_GPS_PROVIDER)
2307@@ -124,3 +125,4 @@
2308
2309 LOCATION_SERVICE_ADD_TEST(remote_provider_test remote_provider_test.cpp)
2310 LOCATION_SERVICE_ADD_TEST(espoo_provider_test espoo_provider_test.cpp)
2311+LOCATION_SERVICE_ADD_TEST(delayed_service_test delayed_service_test.cpp)
2312
2313=== modified file 'tests/acceptance_tests.cpp'
2314--- tests/acceptance_tests.cpp 2015-02-13 13:19:18 +0000
2315+++ tests/acceptance_tests.cpp 2016-01-25 14:24:35 +0000
2316@@ -38,12 +38,14 @@
2317 #include <com/ubuntu/location/service/stub.h>
2318
2319 #include <core/dbus/announcer.h>
2320+#include <core/dbus/bus.h>
2321 #include <core/dbus/fixture.h>
2322 #include <core/dbus/resolver.h>
2323
2324 #include <core/dbus/asio/executor.h>
2325
2326 #include <core/posix/signal.h>
2327+#include <core/posix/this_process.h>
2328
2329 #include <core/testing/cross_process_sync.h>
2330 #include <core/testing/fork_and_run.h>
2331@@ -663,6 +665,110 @@
2332 EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(server, client));
2333 }
2334
2335+TEST_F(LocationServiceStandalone, NewSessionsGetLastKnownPosition)
2336+{
2337+ core::testing::CrossProcessSync sync_start;
2338+
2339+ auto server = [this, &sync_start]()
2340+ {
2341+ SCOPED_TRACE("Server");
2342+
2343+ auto trap = core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_term});
2344+ trap->signal_raised().connect([trap](core::posix::Signal)
2345+ {
2346+ trap->stop();
2347+ });
2348+
2349+ auto incoming = session_bus();
2350+ auto outgoing = session_bus();
2351+
2352+ incoming->install_executor(core::dbus::asio::make_executor(incoming));
2353+ outgoing->install_executor(core::dbus::asio::make_executor(outgoing));
2354+
2355+ auto dummy = new DummyProvider();
2356+ cul::Provider::Ptr helper(dummy);
2357+
2358+ cul::service::DefaultConfiguration config;
2359+ cul::service::Implementation::Configuration configuration
2360+ {
2361+ incoming,
2362+ outgoing,
2363+ config.the_engine(config.the_provider_set(helper), config.the_provider_selection_policy(), null_settings()),
2364+ config.the_permission_manager(incoming),
2365+ cul::service::Harvester::Configuration
2366+ {
2367+ cul::connectivity::platform_default_manager(),
2368+ std::make_shared<NullReporter>()
2369+ }
2370+ };
2371+ auto location_service = std::make_shared<cul::service::Implementation>(configuration);
2372+
2373+ configuration.engine->updates.last_known_location.set(reference_position_update);
2374+ std::thread t1{[incoming](){incoming->run();}};
2375+ std::thread t2{[outgoing](){outgoing->run();}};
2376+
2377+ sync_start.try_signal_ready_for(std::chrono::milliseconds{500});
2378+
2379+ trap->run();
2380+
2381+ incoming->stop();
2382+ outgoing->stop();
2383+
2384+ if (t1.joinable())
2385+ t1.join();
2386+
2387+ if (t2.joinable())
2388+ t2.join();
2389+
2390+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
2391+ };
2392+
2393+ auto client = [this, &sync_start]()
2394+ {
2395+ SCOPED_TRACE("Client");
2396+
2397+ EXPECT_EQ(1, sync_start.wait_for_signal_ready_for(std::chrono::milliseconds{500}));
2398+
2399+ auto bus = session_bus();
2400+ bus->install_executor(dbus::asio::make_executor(bus));
2401+ std::thread t{[bus](){bus->run();}};
2402+
2403+ auto location_service = dbus::resolve_service_on_bus<
2404+ cul::service::Interface,
2405+ cul::service::Stub>(bus);
2406+
2407+ auto s1 = location_service->create_session_for_criteria(cul::Criteria{});
2408+
2409+ std::cout << "Successfully created session" << std::endl;
2410+
2411+ cul::Update<cul::Position> position;
2412+ auto c1 = s1->updates().position.changed().connect(
2413+ [&](const cul::Update<cul::Position>& new_position) {
2414+ std::cout << "On position updated: " << new_position << std::endl;
2415+ position = new_position;
2416+ });
2417+
2418+ std::cout << "Created event connections, starting updates..." << std::endl;
2419+
2420+ s1->updates().position_status = culss::Interface::Updates::Status::enabled;
2421+
2422+ std::cout << "done" << std::endl;
2423+
2424+ std::this_thread::sleep_for(std::chrono::milliseconds{1000});
2425+
2426+ bus->stop();
2427+
2428+ if (t.joinable())
2429+ t.join();
2430+
2431+ EXPECT_EQ(reference_position_update, position);
2432+
2433+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success;
2434+ };
2435+
2436+ EXPECT_EQ(core::testing::ForkAndRunResult::empty, core::testing::fork_and_run(server, client));
2437+}
2438+
2439 namespace
2440 {
2441 struct LocationServiceStandaloneLoad : public LocationServiceStandalone
2442@@ -708,7 +814,7 @@
2443
2444 options.add(Keys::update_period,
2445 "Update period length for dummy::Provider setup.",
2446- std::uint32_t{100});
2447+ std::uint32_t{10});
2448
2449 options.add(Keys::client_count,
2450 "Number of clients that should be fired up.",
2451@@ -761,6 +867,8 @@
2452 };
2453 }
2454
2455+#include "did_finish_successfully.h"
2456+
2457 TEST_F(LocationServiceStandaloneLoad, MultipleClientsConnectingAndDisconnectingWorks)
2458 {
2459 EXPECT_TRUE(trust_store_is_set_up_for_testing);
2460@@ -801,8 +909,8 @@
2461 };
2462
2463 cul::service::Daemon::Configuration config;
2464- config.incoming = session_bus();
2465- config.outgoing = session_bus();
2466+ config.incoming = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS"));
2467+ config.outgoing = std::make_shared<core::dbus::Bus>(core::posix::this_process::env::get_or_throw("DBUS_SESSION_BUS_ADDRESS"));
2468 config.is_testing_enabled = false;
2469 config.providers =
2470 {
2471@@ -829,7 +937,7 @@
2472 status;
2473 }, core::posix::StandardStream::empty);
2474
2475- std::this_thread::sleep_for(std::chrono::seconds{2});
2476+ std::this_thread::sleep_for(std::chrono::seconds{15});
2477
2478 auto client = [this]()
2479 {
2480@@ -957,17 +1065,11 @@
2481 {
2482 VLOG(1) << "Stopping client...: " << client.pid();
2483 client.send_signal_or_throw(core::posix::Signal::sig_term);
2484- auto result = client.wait_for(core::posix::wait::Flags::untraced);
2485-
2486- EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status);
2487- EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status);
2488+ EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced)));
2489 }
2490
2491 VLOG(1) << "Cleaned up clients, shutting down the service...";
2492
2493 server.send_signal_or_throw(core::posix::Signal::sig_term);
2494- auto result = server.wait_for(core::posix::wait::Flags::untraced);
2495-
2496- EXPECT_EQ(core::posix::wait::Result::Status::exited, result.status);
2497- EXPECT_EQ(core::posix::exit::Status::success, result.detail.if_exited.status);
2498+ EXPECT_TRUE(did_finish_successfully(server.wait_for(core::posix::wait::Flags::untraced)));
2499 }
2500
2501=== added file 'tests/delayed_service_test.cpp'
2502--- tests/delayed_service_test.cpp 1970-01-01 00:00:00 +0000
2503+++ tests/delayed_service_test.cpp 2016-01-25 14:24:35 +0000
2504@@ -0,0 +1,193 @@
2505+/*
2506+ * Copyright © 2014 Canonical Ltd.
2507+ *
2508+ * This program is free software: you can redistribute it and/or modify it
2509+ * under the terms of the GNU Lesser General Public License version 3,
2510+ * as published by the Free Software Foundation.
2511+ *
2512+ * This program is distributed in the hope that it will be useful,
2513+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2514+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2515+ * GNU Lesser General Public License for more details.
2516+ *
2517+ * You should have received a copy of the GNU Lesser General Public License
2518+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2519+ *
2520+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2521+ * Scott Sweeny <scott.sweeny@canonical.com>
2522+ */
2523+
2524+#include <com/ubuntu/location/service/daemon.h>
2525+#include <com/ubuntu/location/service/provider_daemon.h>
2526+#include <com/ubuntu/location/providers/remote/provider.h>
2527+
2528+#include <com/ubuntu/location/service/stub.h>
2529+
2530+#include <com/ubuntu/location/position.h>
2531+#include <com/ubuntu/location/update.h>
2532+
2533+#include <core/dbus/fixture.h>
2534+
2535+#include <core/dbus/asio/executor.h>
2536+
2537+#include <core/posix/fork.h>
2538+#include <core/posix/signal.h>
2539+#include <core/posix/this_process.h>
2540+
2541+#include "did_finish_successfully.h"
2542+#include "mock_event_receiver.h"
2543+
2544+#include <gmock/gmock.h>
2545+
2546+namespace location = com::ubuntu::location;
2547+namespace remote = com::ubuntu::location::providers::remote;
2548+
2549+namespace
2550+{
2551+struct DelayedServiceTest : public core::dbus::testing::Fixture, public ::testing::WithParamInterface<int>
2552+{
2553+
2554+};
2555+}
2556+
2557+TEST_P(DelayedServiceTest, AClientReceivesUpdatesFromADelayedProvider)
2558+{
2559+ auto oopp = core::posix::fork([this]()
2560+ {
2561+ auto bus = session_bus();
2562+
2563+ // Pass the delay value to the provider
2564+ char delay[50];
2565+ sprintf(delay, "--dummy::DelayedProvider::DelayInMs=%d", GetParam());
2566+
2567+ const char* argv[] =
2568+ {
2569+ "--bus", "session", // 2
2570+ "--service-name", "com.ubuntu.location.providers.Dummy", // 4
2571+ "--service-path", "/com/ubuntu/location/providers/Dummy", // 6
2572+ "--provider", "dummy::DelayedProvider", // 8
2573+ delay // 9
2574+ };
2575+
2576+ auto dbus_connection_factory = [bus](core::dbus::WellKnownBus)
2577+ {
2578+ return bus;
2579+ };
2580+
2581+ return static_cast<core::posix::exit::Status>(
2582+ location::service::ProviderDaemon::main(
2583+ location::service::ProviderDaemon::Configuration::from_command_line_args(
2584+ 9, argv, dbus_connection_factory)));
2585+ }, core::posix::StandardStream::empty);
2586+
2587+ std::this_thread::sleep_for(std::chrono::milliseconds{250});
2588+
2589+ auto service = core::posix::fork([this]()
2590+ {
2591+ core::posix::this_process::env::set_or_throw(
2592+ "TRUST_STORE_PERMISSION_MANAGER_IS_RUNNING_UNDER_TESTING",
2593+ "1");
2594+
2595+ const char* argv[] =
2596+ {
2597+ "--bus", "session", // 2
2598+ "--provider", "remote::Provider", // 4
2599+ "--remote::Provider::bus=session_with_address_from_env", // 5
2600+ "--remote::Provider::name=com.ubuntu.location.providers.Dummy", // 6
2601+ "--remote::Provider::path=/com/ubuntu/location/providers/Dummy" // 7
2602+ };
2603+
2604+ // The daemon instance requires two bus instances.
2605+ auto dbus_connection_factory = [this](core::dbus::WellKnownBus)
2606+ {
2607+ return session_bus();
2608+ };
2609+
2610+ return static_cast<core::posix::exit::Status>(
2611+ location::service::Daemon::main(
2612+ location::service::Daemon::Configuration::from_command_line_args(
2613+ 7, argv, dbus_connection_factory)));
2614+ }, core::posix::StandardStream::empty);
2615+
2616+ // Wait to setup the client until the service is up
2617+ std::this_thread::sleep_for(std::chrono::milliseconds{250 + GetParam()});
2618+
2619+ auto client = core::posix::fork([this]()
2620+ {
2621+ using namespace ::testing;
2622+
2623+ auto trap = core::posix::trap_signals_for_all_subsequent_threads(
2624+ {
2625+ core::posix::Signal::sig_term,
2626+ core::posix::Signal::sig_int
2627+ });
2628+
2629+ trap->signal_raised().connect([trap](const core::posix::Signal&)
2630+ {
2631+ trap->stop();
2632+ });
2633+
2634+ auto bus = session_bus();
2635+ bus->install_executor(core::dbus::asio::make_executor(bus));
2636+
2637+ std::thread worker
2638+ {
2639+ [bus]() { bus->run(); }
2640+ };
2641+
2642+ MockEventReceiver receiver;
2643+ EXPECT_CALL(receiver, position_update_received(_)).Times(AtLeast(1));
2644+ EXPECT_CALL(receiver, heading_update_received(_)).Times(AtLeast(1));
2645+ EXPECT_CALL(receiver, velocity_update_received(_)).Times(AtLeast(1));
2646+
2647+ com::ubuntu::location::service::Stub service{bus};
2648+
2649+ auto session = service.create_session_for_criteria(location::Criteria{});
2650+
2651+ session->updates().position.changed().connect([&receiver](location::Update<location::Position> pos)
2652+ {
2653+ receiver.position_update_received(pos);
2654+ });
2655+
2656+ session->updates().heading.changed().connect([&receiver](location::Update<location::Heading> heading)
2657+ {
2658+ receiver.heading_update_received(heading);
2659+ });
2660+
2661+ session->updates().velocity.changed().connect([&receiver](location::Update<location::Velocity> velocity)
2662+ {
2663+ receiver.velocity_update_received(velocity);
2664+ });
2665+
2666+ session->updates().position_status = location::service::session::Interface::Updates::Status::enabled;
2667+ session->updates().velocity_status = location::service::session::Interface::Updates::Status::enabled;
2668+ session->updates().heading_status = location::service::session::Interface::Updates::Status::enabled;
2669+
2670+ trap->run();
2671+
2672+ bus->stop();
2673+
2674+ if (worker.joinable())
2675+ worker.join();
2676+
2677+ return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure :
2678+ core::posix::exit::Status::success;
2679+ }, core::posix::StandardStream::empty);
2680+
2681+ std::this_thread::sleep_for(std::chrono::milliseconds{4000});
2682+
2683+ std::cout << "Shutting down client" << std::endl;
2684+ client.send_signal_or_throw(core::posix::Signal::sig_term);
2685+ EXPECT_TRUE(did_finish_successfully(client.wait_for(core::posix::wait::Flags::untraced)));
2686+
2687+ std::cout << "Shutting down service" << std::endl;
2688+ service.send_signal_or_throw(core::posix::Signal::sig_term);
2689+ EXPECT_TRUE(did_finish_successfully(service.wait_for(core::posix::wait::Flags::untraced)));
2690+
2691+ std::cout << "Shutting down oopp" << std::endl;
2692+ oopp.send_signal_or_throw(core::posix::Signal::sig_term);
2693+ EXPECT_TRUE(did_finish_successfully(oopp.wait_for(core::posix::wait::Flags::untraced)));
2694+}
2695+
2696+INSTANTIATE_TEST_CASE_P(ServiceDelays, DelayedServiceTest,
2697+ ::testing::Values(0, 250, 500, 1000, 2000, 5000, 10000));
2698
2699=== modified file 'tests/engine_test.cpp'
2700--- tests/engine_test.cpp 2015-01-21 20:04:56 +0000
2701+++ tests/engine_test.cpp 2016-01-25 14:24:35 +0000
2702@@ -154,9 +154,9 @@
2703 EXPECT_CALL(*provider, on_reference_velocity_updated(_)).Times(1);
2704
2705 engine.configuration.wifi_and_cell_id_reporting_state = location::WifiAndCellIdReportingState::on;
2706- engine.updates.reference_location = location::Update<location::Position>{};
2707- engine.updates.reference_heading = location::Update<location::Heading>{};
2708- engine.updates.reference_velocity = location::Update<location::Velocity>{};
2709+ engine.updates.last_known_location = location::Update<location::Position>{};
2710+ engine.updates.last_known_heading = location::Update<location::Heading>{};
2711+ engine.updates.last_known_velocity = location::Update<location::Velocity>{};
2712 }
2713
2714 /* TODO(tvoss): We have to disable these tests as the MP is being refactored to not break ABI.
2715
2716=== modified file 'tests/gps_provider_test.cpp'
2717--- tests/gps_provider_test.cpp 2015-01-12 08:41:14 +0000
2718+++ tests/gps_provider_test.cpp 2016-01-25 14:24:35 +0000
2719@@ -48,6 +48,31 @@
2720
2721 namespace
2722 {
2723+
2724+struct MockHardwareGps
2725+{
2726+ MockHardwareGps()
2727+ {
2728+ instance_ = this;
2729+ }
2730+ ~MockHardwareGps()
2731+ {
2732+ instance_ = nullptr;
2733+ }
2734+
2735+ MOCK_METHOD5(set_position_mode, bool(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t));
2736+ MOCK_METHOD3(inject_time, void(int64_t, int64_t, int));
2737+
2738+ static MockHardwareGps *mocked(UHardwareGps self) {
2739+ return reinterpret_cast<MockHardwareGps*>(self);
2740+ }
2741+ static MockHardwareGps *instance() { return instance_; }
2742+
2743+ static MockHardwareGps *instance_;
2744+};
2745+
2746+MockHardwareGps *MockHardwareGps::instance_ = nullptr;
2747+
2748 struct UpdateTrap
2749 {
2750 MOCK_METHOD1(on_position_updated, void(const location::Position&));
2751@@ -211,6 +236,42 @@
2752
2753 }
2754
2755+/* Mock the hardware GPS platform API: the methods defined here will be invoked
2756+ * instead of those exported by the system library.
2757+ * We redefine these methods using the MockHardwareGps class above, which is
2758+ * implemented using google-mock. This effectively allows us to test that the
2759+ * right calls to the platform API are made.
2760+ */
2761+UHardwareGps
2762+u_hardware_gps_new(UHardwareGpsParams *)
2763+{
2764+ using namespace ::testing;
2765+
2766+ return reinterpret_cast<UHardwareGps>(MockHardwareGps::instance());
2767+}
2768+
2769+void
2770+u_hardware_gps_delete(UHardwareGps)
2771+{
2772+}
2773+
2774+bool
2775+u_hardware_gps_set_position_mode(UHardwareGps self, uint32_t mode, uint32_t recurrence,
2776+ uint32_t min_interval, uint32_t preferred_accuracy,
2777+ uint32_t preferred_time)
2778+{
2779+ MockHardwareGps *thiz = MockHardwareGps::mocked(self);
2780+ return thiz->set_position_mode(mode, recurrence, min_interval,
2781+ preferred_accuracy, preferred_time);
2782+}
2783+
2784+void
2785+u_hardware_gps_inject_time(UHardwareGps self, int64_t time, int64_t time_reference, int uncertainty)
2786+{
2787+ MockHardwareGps* thiz = MockHardwareGps::mocked(self);
2788+ return thiz->inject_time(time, time_reference, uncertainty);
2789+}
2790+
2791 TEST(AndroidGpsXtraDownloader, reading_configuration_from_valid_conf_file_works)
2792 {
2793 std::stringstream ss{gps_conf};
2794@@ -261,6 +322,28 @@
2795 provider.on_reference_location_updated(pos);
2796 }
2797
2798+TEST(GpsProvider, time_requests_inject_current_time_into_the_hal)
2799+{
2800+ using namespace ::testing;
2801+
2802+ NiceMock<MockHardwareGps> hardwareGps;
2803+
2804+ gps::android::HardwareAbstractionLayer::Configuration configuration;
2805+ gps::android::HardwareAbstractionLayer hal(configuration);
2806+ std::shared_ptr<gps::HardwareAbstractionLayer> hal_ptr(&hal, [](gps::HardwareAbstractionLayer*){});
2807+
2808+ gps::Provider provider(hal_ptr);
2809+ int64_t time = 0;
2810+ EXPECT_CALL(hardwareGps, inject_time(_, _, 0)).Times(1).WillOnce(SaveArg<0>(&time));
2811+
2812+ auto t0 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
2813+
2814+ gps::android::HardwareAbstractionLayer::on_request_utc_time(&hal);
2815+
2816+ auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(location::Clock::now().time_since_epoch());
2817+ EXPECT_THAT(time, AllOf(Ge(t0.count()), Le(t1.count())));
2818+}
2819+
2820 TEST(GpsProvider, updates_from_hal_are_passed_on_by_the_provider)
2821 {
2822 using namespace ::testing;
2823
2824=== added file 'tests/mock_event_receiver.h'
2825--- tests/mock_event_receiver.h 1970-01-01 00:00:00 +0000
2826+++ tests/mock_event_receiver.h 2016-01-25 14:24:35 +0000
2827@@ -0,0 +1,35 @@
2828+/*
2829+ * Copyright © 2015 Canonical Ltd.
2830+ *
2831+ * This program is free software: you can redistribute it and/or modify it
2832+ * under the terms of the GNU Lesser General Public License version 3,
2833+ * as published by the Free Software Foundation.
2834+ *
2835+ * This program is distributed in the hope that it will be useful,
2836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2838+ * GNU Lesser General Public License for more details.
2839+ *
2840+ * You should have received a copy of the GNU Lesser General Public License
2841+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2842+ *
2843+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2844+ * Scott Sweeny <scott.sweeny@canonical.com>
2845+ */
2846+#ifndef MOCK_EVENT_RECEIVER_H_
2847+#define MOCK_EVENT_RECEIVER_H_
2848+
2849+#include <com/ubuntu/location/update.h>
2850+
2851+#include <gmock/gmock.h>
2852+
2853+namespace location = com::ubuntu::location;
2854+
2855+struct MockEventReceiver
2856+{
2857+ MOCK_METHOD1(position_update_received, void(const location::Update<location::Position>&));
2858+ MOCK_METHOD1(heading_update_received, void(const location::Update<location::Heading>&));
2859+ MOCK_METHOD1(velocity_update_received, void(const location::Update<location::Velocity>&));
2860+};
2861+
2862+#endif // MOCK_EVENT_RECEIVER_H_
2863
2864=== modified file 'tests/position_test.cpp'
2865--- tests/position_test.cpp 2014-06-20 07:40:34 +0000
2866+++ tests/position_test.cpp 2016-01-25 14:24:35 +0000
2867@@ -40,7 +40,7 @@
2868 cul::wgs84::Latitude{},
2869 cul::wgs84::Longitude{},
2870 cul::wgs84::Altitude{}};
2871- EXPECT_TRUE(p.altitude);
2872+ EXPECT_TRUE(p.altitude ? true : false);
2873 }
2874
2875 #include <com/ubuntu/location/codec.h>
2876
2877=== modified file 'tests/remote_providerd_test.cpp'
2878--- tests/remote_providerd_test.cpp 2014-10-27 21:58:16 +0000
2879+++ tests/remote_providerd_test.cpp 2016-01-25 14:24:35 +0000
2880@@ -31,6 +31,7 @@
2881 #include <core/posix/fork.h>
2882
2883 #include "did_finish_successfully.h"
2884+#include "mock_event_receiver.h"
2885
2886 #include <gmock/gmock.h>
2887
2888@@ -38,13 +39,6 @@
2889
2890 namespace
2891 {
2892-struct MockEventReceiver
2893-{
2894- MOCK_METHOD1(position_update_received, void(const location::Update<location::Position>&));
2895- MOCK_METHOD1(heading_update_received, void(const location::Update<location::Heading>&));
2896- MOCK_METHOD1(velocity_update_received, void(const location::Update<location::Velocity>&));
2897-};
2898-
2899 struct RemoteProviderdTest : public core::dbus::testing::Fixture
2900 {
2901
2902
2903=== added file 'tests/runtime_test.cpp'
2904--- tests/runtime_test.cpp 1970-01-01 00:00:00 +0000
2905+++ tests/runtime_test.cpp 2016-01-25 14:24:35 +0000
2906@@ -0,0 +1,118 @@
2907+/*
2908+ * Copyright © 2015Canonical Ltd.
2909+ *
2910+ * This program is free software: you can redistribute it and/or modify it
2911+ * under the terms of the GNU Lesser General Public License version 3,
2912+ * as published by the Free Software Foundation.
2913+ *
2914+ * This program is distributed in the hope that it will be useful,
2915+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2916+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2917+ * GNU Lesser General Public License for more details.
2918+ *
2919+ * You should have received a copy of the GNU Lesser General Public License
2920+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2921+ *
2922+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
2923+ */
2924+#include <com/ubuntu/location/service/runtime.h>
2925+
2926+#include <gtest/gtest.h>
2927+
2928+#include <condition_variable>
2929+#include <thread>
2930+
2931+namespace culs = com::ubuntu::location::service;
2932+
2933+TEST(Runtime, cleanly_shuts_down_threads)
2934+{
2935+ culs::Runtime::create();
2936+}
2937+
2938+TEST(Runtime, executes_service)
2939+{
2940+ std::mutex m;
2941+ std::unique_lock<std::mutex> ul{m};
2942+ std::condition_variable wc;
2943+
2944+ bool signaled = false;
2945+
2946+ auto rt = culs::Runtime::create();
2947+ rt->start();
2948+ boost::asio::deadline_timer timer{rt->service(), boost::posix_time::milliseconds(500)};
2949+ timer.async_wait([&wc, &signaled](const boost::system::error_code&)
2950+ {
2951+ signaled = true;
2952+ wc.notify_all();
2953+ });
2954+
2955+ auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; });
2956+ EXPECT_TRUE(result);
2957+}
2958+
2959+TEST(Runtime, catches_exceptions_thrown_from_handlers)
2960+{
2961+ std::mutex m;
2962+ std::unique_lock<std::mutex> ul{m};
2963+ std::condition_variable wc;
2964+
2965+ bool signaled = false;
2966+
2967+ auto rt = culs::Runtime::create();
2968+ rt->start();
2969+ boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)};
2970+ fast.async_wait([](const boost::system::error_code&)
2971+ {
2972+ throw std::runtime_error{"Should not propagate"};
2973+ });
2974+
2975+ boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)};
2976+ slow.async_wait([&wc, &signaled](const boost::system::error_code&)
2977+ {
2978+ signaled = true;
2979+ wc.notify_all();
2980+ });
2981+
2982+ auto result = wc.wait_for(ul, std::chrono::seconds{1}, [&signaled]() { return signaled; });
2983+ EXPECT_TRUE(result);
2984+}
2985+
2986+// sets_up_pool_of_threads ensures that the pool size
2987+// passed to the Runtime on construction is honored. The idea is simple:
2988+// We set up two deadline timers, fast and slow. fast fires before slow,
2989+// with fast blocking in a wait on a common condition_variable. When slow
2990+// fires, it notifies the condition variable, thereby unblocking the handler of fast,
2991+// enabling clean shutdown without errors and timeouts. This only works if the
2992+// pool contains at least 2 threads. Otherwise, the handler of slow would not be executed
2993+// until the handler of fast times out in the wait, marking the test as failed.
2994+TEST(Runtime, sets_up_pool_of_threads)
2995+{
2996+ struct State
2997+ {
2998+ bool signaled{false};
2999+ std::mutex m;
3000+ std::condition_variable wc;
3001+ };
3002+
3003+ auto state = std::make_shared<State>();
3004+
3005+ auto rt = culs::Runtime::create(2);
3006+ rt->start();
3007+ boost::asio::deadline_timer fast{rt->service(), boost::posix_time::milliseconds(100)};
3008+ fast.async_wait([state](const boost::system::error_code&)
3009+ {
3010+ std::unique_lock<std::mutex> ul{state->m};
3011+ EXPECT_TRUE(state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; }));
3012+ });
3013+
3014+ boost::asio::deadline_timer slow{rt->service(), boost::posix_time::milliseconds(500)};
3015+ slow.async_wait([state](const boost::system::error_code&)
3016+ {
3017+ state->signaled = true;
3018+ state->wc.notify_all();
3019+ });
3020+
3021+ std::unique_lock<std::mutex> ul{state->m};
3022+ auto result = state->wc.wait_for(ul, std::chrono::seconds{1}, [state]() { return state->signaled; });
3023+ EXPECT_TRUE(result);
3024+}
3025
3026=== added directory 'tools'
3027=== added file 'tools/CMakeLists.txt'
3028--- tools/CMakeLists.txt 1970-01-01 00:00:00 +0000
3029+++ tools/CMakeLists.txt 2016-01-25 14:24:35 +0000
3030@@ -0,0 +1,1 @@
3031+configure_file(symbol_diff.in symbol_diff)
3032
3033=== added file 'tools/symbol_diff.in'
3034--- tools/symbol_diff.in 1970-01-01 00:00:00 +0000
3035+++ tools/symbol_diff.in 2016-01-25 14:24:35 +0000
3036@@ -0,0 +1,70 @@
3037+#! /usr/bin/env python3
3038+
3039+#
3040+# Copyright (C) 2014 Canonical Ltd
3041+#
3042+# This program is free software: you can redistribute it and/or modify
3043+# it under the terms of the GNU Lesser General Public License version 3 as
3044+# published by the Free Software Foundation.
3045+#
3046+# This program is distributed in the hope that it will be useful,
3047+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3048+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3049+# GNU Lesser General Public License for more details.
3050+#
3051+# You should have received a copy of the GNU Lesser General Public License
3052+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3053+#
3054+# Authored by: Michi Henning <michi.henning@canonical.com>
3055+#
3056+
3057+import re
3058+import subprocess
3059+
3060+OLD_FILE = './debian/libubuntu-location-service@UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@.symbols'
3061+NEW_FILE = './debian/libubuntu-location-service@UBUNTU_LOCATION_SERVICE_VERSION_MAJOR@/DEBIAN/symbols'
3062+
3063+def run():
3064+ old_regex = re.compile(r'^ (\(.*\))"(.*)" (.*)$')
3065+
3066+ old_syms = {} # Dictionary containing symbol -> ( tag, version )
3067+ with open(OLD_FILE, encoding='utf=8') as file:
3068+ file.readline() # Skip first line, which is the library name and version
3069+ for line in file:
3070+ mo = old_regex.match(line)
3071+ if mo:
3072+ old_syms[mo.group(2)] = ( mo.group(1), mo.group(3) )
3073+ else:
3074+ raise Exception('Invalid input line in ' + OLD_FILE + ': ' + line)
3075+
3076+ new_regex = re.compile(r'^ (.*) .+$')
3077+
3078+ # Run the new symbols file through "c++filt | sort | uniq". We need
3079+ # the sort | uniq because, otherwise, we end up with duplicate demangled symbols.
3080+ with open(NEW_FILE) as infile, open('new_symbols', 'w') as outfile:
3081+ p = subprocess.Popen(['c++filt | sort | uniq'], shell=True, stdin=infile, stdout=subprocess.PIPE)
3082+
3083+ # For each symbol, if it is in the old dictionary, output the tags from the original
3084+ # symbol file, followed by the symbol and version. Otherwise, use "(c++)" as the tag
3085+ # and add " 0replaceme", so the new symbol will be accepted.
3086+ line = p.stdout.readline().decode('utf-8')
3087+ outfile.write(line) # Write library name and version
3088+ for line in p.stdout:
3089+ mo = new_regex.match(line.decode('utf-8'))
3090+ if (mo):
3091+ sym = mo.group(1)
3092+ try:
3093+ tag, version = old_syms[sym]
3094+ except KeyError:
3095+ tag = '(c++)'
3096+ version = '0replaceme'
3097+ outfile.write(' {}"{}" {}\n'.format(tag, sym, version))
3098+ else:
3099+ raise Exception('Cannot parse demangled line: ' + line)
3100+
3101+ # Write the diff into /tmp/symbols.diff
3102+ with open('/tmp/symbols.diff', 'w') as outfile:
3103+ subprocess.call(['diff', '-u', OLD_FILE, 'new_symbols'], stdout=outfile)
3104+
3105+if __name__ == '__main__':
3106+ run()

Subscribers

People subscribed via source and target branches