diff --git a/README.md b/README.md index fc0bbc2..adfafd7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Android (Kotlin) SDK for manipulating GPX files +![](https://img.shields.io/maven-central/v/me.bvn13.sdk.android.gpx/GpxAndroidSdk) + ## About This is another one SDK for reading and writing (manipulating) GPX files. @@ -8,6 +10,12 @@ Official GPX format is on [topografix](https://www.topografix.com/GPX/1/1/) site ## Changelog +### 2023-02-13 + +1) Fixed missed extensions +2) ✅ Tested on reading with self written content +3) ✅ Tested on reading [OsmAnd](https://osmand.net) GPX files + ### 2022-12-18 1) implemented GPX format reader diff --git a/src/main/kotlin/me/bvn13/sdk/android/gpx/ExtensionType.kt b/src/main/kotlin/me/bvn13/sdk/android/gpx/ExtensionType.kt index fa6dc89..236cb9a 100644 --- a/src/main/kotlin/me/bvn13/sdk/android/gpx/ExtensionType.kt +++ b/src/main/kotlin/me/bvn13/sdk/android/gpx/ExtensionType.kt @@ -92,10 +92,13 @@ package me.bvn13.sdk.android.gpx * * [parameters] Map of key-value pairs */ -class ExtensionType(val nodeName: String, val value: String? = null, val parameters: Map? = null) { +class ExtensionType(val nodeName: String, + val value: String? = null, + val parameters: Map? = null, + val nested: List? = null) { init { - require(value != null || parameters != null) { - "value or parameters must be specified" + require(value != null || parameters != null || nested != null) { + "value or parameters or nesting elements must be specified for ${nodeName}" } } @@ -108,6 +111,7 @@ class ExtensionType(val nodeName: String, val value: String? = null, val paramet if (nodeName != other.nodeName) return false if (value != other.value) return false if (parameters != other.parameters) return false + if (nested != other.nested) return false return true } @@ -116,8 +120,7 @@ class ExtensionType(val nodeName: String, val value: String? = null, val paramet var result = nodeName.hashCode() result = 31 * result + (value?.hashCode() ?: 0) result = 31 * result + (parameters?.hashCode() ?: 0) + result = 31 * result + (nested?.hashCode() ?: 0) return result } - - } diff --git a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxConstant.kt b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxConstant.kt index dd1d716..4ee1377 100644 --- a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxConstant.kt +++ b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxConstant.kt @@ -6,6 +6,7 @@ import java.time.format.DateTimeFormatterBuilder class GpxConstant { companion object { const val HEADER = "" + const val HEADER_EXTENDED = "" const val VERSION = "1.1" val DTF = DateTimeFormatterBuilder().append(ISO_LOCAL_DATE_TIME) // use the existing formatter for date time diff --git a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxReader.kt b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxReader.kt index 83f1b31..1687ca6 100644 --- a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxReader.kt +++ b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxReader.kt @@ -3,6 +3,7 @@ package me.bvn13.sdk.android.gpx import me.bvn13.sdk.android.gpx.GpxConstant.Companion.DTF import java.io.InputStream import java.time.OffsetDateTime +import java.util.stream.Collectors fun GpxType.Companion.read(dis: InputStream) = GpxReader().read(dis) @@ -28,7 +29,13 @@ class GpxReader { private fun readSignature(dis: InputStream, buffer: Container): GpxType { val container = readUntil(dis, buffer, '\n') - if ("${GpxConstant.HEADER}\n" != container.buffer.asString()) { + val signaturePrepared = container.buffer.asString() + .trim() + .replace("'", "\"") + .replace(" ?", "?") + if (GpxConstant.HEADER != signaturePrepared + && GpxConstant.HEADER_EXTENDED != signaturePrepared + ) { throw IllegalArgumentException("Wrong xml signature!") } return readBeginning(dis, Container.empty(container.position)) @@ -59,10 +66,12 @@ class GpxReader { return findObject(container.objects, "gpx").let { return GpxType( metadata = assembleMetadataType(it.nested), - creator = findAttributeOrNull(it.attributes, "creator") ?: throw IllegalArgumentException("Gpx.Creator not found"), - wpt = findObjectsOrNull(it.nested ,"wpt")?.map { assembleWptType(it) }, + creator = findAttributeOrNull(it.attributes, "creator") + ?: throw IllegalArgumentException("Gpx.Creator not found"), + wpt = findObjectsOrNull(it.nested, "wpt")?.map { assembleWptType(it) }, rte = findObjectsOrNull(it.nested, "rte")?.map { assembleRteType(it) }, - trk = findObjectsOrNull(it.nested, "trk")?.map { assembleTrkType(it) } + trk = findObjectsOrNull(it.nested, "trk")?.map { assembleTrkType(it) }, + extensions = findObjectOrNull(it.nested, "extensions")?.let { assembleExtensionType(it) } ) } } @@ -71,10 +80,13 @@ class GpxReader { findObject(objects, "metadata") .let { return MetadataType( - name = findObjectOrNull(it.nested, "name")?.value ?: throw IllegalArgumentException("Gpx.Metadata.Name not found"), - description = findObjectOrNull(it.nested, "desc")?.value ?: throw IllegalArgumentException("Gpx.Metadata.Description not found"), - authorName = findObject(it.nested, "author").let { author -> - findObject(author.nested, "name").value ?: throw IllegalArgumentException("Gpx.Metadata.Author.Name not found") + name = findObjectOrNull(it.nested, "name")?.value + ?: throw IllegalArgumentException("Gpx.Metadata.Name not found"), + description = findObjectOrNull(it.nested, "desc")?.value + ?: "", + authorName = findObjectOrNull(it.nested, "author").let { author -> + findObjectOrNull(author?.nested, "name")?.value + ?: "" } ) } @@ -123,7 +135,10 @@ class GpxReader { cmt = findObjectOrNull(obj.nested, "cmt")?.value, desc = findObjectOrNull(obj.nested, "desc")?.value, src = findObjectOrNull(obj.nested, "src")?.value, - link = findObjectsOrNull(obj.nested, "link")?.let { list -> if (list.isNotEmpty()) list.map { assembleLinkType(it) } else null }, + link = findObjectsOrNull( + obj.nested, + "link" + )?.let { list -> if (list.isNotEmpty()) list.map { assembleLinkType(it) } else null }, number = findObjectOrNull(obj.nested, "number")?.value?.toInt(), type = findObjectOrNull(obj.nested, "type")?.value, extensions = findObjectOrNull(obj.nested, "extensions")?.let { assembleExtensionType(it) }, @@ -140,12 +155,17 @@ class GpxReader { private fun assembleFixType(value: String): FixType = FixType.valueOf(value.uppercase()) - private fun assembleExtensionType(obj: XmlObject): ExtensionType = - ExtensionType( + private fun assembleExtensionType(obj: XmlObject): ExtensionType { + val nested: List? = obj.nested?.stream() + ?.map { assembleExtensionType(it) } + ?.collect(Collectors.toList()) + return ExtensionType( nodeName = obj.type, value = if (obj.value == "") null else obj.value, - parameters = if (obj.attributes.isEmpty()) null else obj.attributes.toSortedMap() - ) + parameters = if (obj.attributes.isEmpty()) null else obj.attributes.toSortedMap(), + nested = nested + ) + } private fun assembleTrksegType(obj: XmlObject): TrksegType = TrksegType( @@ -186,14 +206,16 @@ class GpxReader { container = readAttributes(dis, container) xmlObject.attributes = container.attributes } - container = readSkipping(dis, container, SKIPPING_SET) - if (container.byte!!.toInt() == '<'.code) { - container = readNestedObjects(dis, container) - xmlObject.nested = container.objects - container = readFinishingTag(dis, container, tagName) - } - if (container.buffer.asString() != "") { - container = readValue(dis, container, tagName) + if (!container.isShortClosing) { + container = readSkipping(dis, container, SKIPPING_SET) + if (container.byte!!.toInt() == '<'.code) { + container = readNestedObjects(dis, container) + xmlObject.nested = container.objects + container = readFinishingTag(dis, container, tagName) + } + if (container.buffer.asString() != "") { + container = readValue(dis, container, tagName) + } } xmlObject.value = container.buffer.asString().replace("", "") container.objects = listOf(xmlObject) @@ -221,8 +243,12 @@ class GpxReader { return container } - private fun readFinishingTag(dis: InputStream, buffer: Container, tagName: String): Container = - readExactly(dis, buffer, "") + private fun readFinishingTag(dis: InputStream, buffer: Container, tagName: String): Container { + if (buffer.isShortClosing) { + return buffer + } + return readExactly(dis, buffer, "") + } private fun readValue(dis: InputStream, buffer: Container, tagName: String): Container = readUntil(dis, buffer, "") @@ -236,8 +262,10 @@ class GpxReader { do { attributeContainer = readAttribute(dis, attributeContainer) attributes.putAll(attributeContainer.attributes) - } while (attributeContainer.attributes.isNotEmpty() && attributeContainer.byte!!.toInt() != '>'.code) - val result = Container.emptyWithAttributes(attributeContainer.position, attributes) + } while (attributeContainer.attributes.isNotEmpty() + && attributeContainer.byte!!.toInt() != '>'.code + ) + val result = Container.emptyWithAttributes(attributeContainer.position, attributes, attributeContainer.isShortClosing) return result } @@ -250,8 +278,17 @@ class GpxReader { val valueAsString = valueContainer.buffer.asString() val value = valueAsString.substring(0, valueAsString.length - 1) val result = Container.empty(valueContainer.position) - val closingContainer = readSkipping(dis, result, SKIPPING_SET) - val nextBlockContainer = Container.of(closingContainer.byte!!, closingContainer.position) + var closingContainer = readSkipping(dis, result, SKIPPING_SET) + var isShortClosing = false + if (closingContainer.byte!!.toInt() == '/'.code) { + val endingContainer = readByte(dis, closingContainer) + if (endingContainer.byte!!.toInt() != '>'.code) { + throw IllegalArgumentException("There must be valid closing tag at ${endingContainer.position}") + } + closingContainer = endingContainer + isShortClosing = true + } + val nextBlockContainer = Container.of(closingContainer.byte!!, closingContainer.position, isShortClosing) nextBlockContainer.attributes = mapOf(name to value) return nextBlockContainer } @@ -321,28 +358,42 @@ class GpxReader { private fun readByte(dis: InputStream, container: Container): Container { val ba = ByteArray(1); if (-1 == dis.read(ba, 0, 1)) { - throw InterruptedException("EOF") + throw InterruptedException("EOF at ${container.position}\nUnparsed data: " + String(container.buffer)) } else if (ba.size != 1) { - throw InterruptedException("Reading of 1 byte returns ${ba.size} bytes") + throw InterruptedException("Reading of 1 byte returns ${ba.size} bytes at ${container.position}") } return Container(container.position + 1, ba[0], container.buffer.plus(ba)) } - class Container(val position: Long = 0, val byte: Byte?, val buffer: ByteArray) { + class Container( + val position: Long = 0, + val byte: Byte?, + val buffer: ByteArray, + val isShortClosing: Boolean = false + ) { var objects: List? = null var attributes: Map = HashMap() var value: String? = null companion object { fun empty(): Container = empty(0) - fun empty(position: Long) = Container(position, null, ByteArray(0)) - fun emptyWithAttributes(position: Long, attributes: Map): Container { - val container = Container.empty(position) + fun empty(position: Long, isShortClosing: Boolean = false) = Container(position, null, ByteArray(0), isShortClosing) + fun emptyWithAttributes(position: Long, attributes: Map, isShortClosing: Boolean = false): Container { + val container = Container.empty(position, isShortClosing) container.attributes = attributes return container } - fun of(b: Byte, position: Long) = Container(position, b, ByteArray(1) { _ -> b }) + fun of(b: Byte, position: Long, isShortClosing: Boolean = false) = + Container(position, b, ByteArray(1) { _ -> b }, isShortClosing) + + fun isShortClosing(c: Container, buffer: ByteArray): Container { + val container = Container(c.position, c.byte, buffer, isShortClosing = true) + container.objects = c.objects + container.attributes = c.attributes + container.value = c.value + return container + } } override fun toString(): String = this.buffer.asString() diff --git a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxWriter.kt b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxWriter.kt index 6160f32..a4005e9 100644 --- a/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxWriter.kt +++ b/src/main/kotlin/me/bvn13/sdk/android/gpx/GpxWriter.kt @@ -100,6 +100,7 @@ fun GpxType.toXmlString(clock: Clock?): String = """ ${this.wpt?.toXmlString() ?: ""} ${this.rte?.toXmlString() ?: ""} ${this.trk?.toXmlString() ?: ""} + ${this.extensions?.toXmlString() ?: ""} """.trim().removeEmptyStrings() @@ -140,7 +141,7 @@ fun WptType.toXmlString(nodeName: String) = """ ${toXmlString(pdop, "pdop")} ${toXmlString(ageofgpsdata, "ageofgpsdata")} ${toXmlString(dgpsid, "dgpsid")} - ${extensions?.toXmlString() ?: ""} + ${extensions?.toXmlString(true) ?: ""} """.trim().removeEmptyStrings() @@ -153,7 +154,7 @@ fun RteType.toXmlString() = """ ${this.link?.toXmlString() ?: ""} ${toXmlString(this.number, "number")} ${toXmlString(this.type, "type")} - ${this.extensions?.toXmlString() ?: ""} + ${this.extensions?.toXmlString(true) ?: ""} ${this.rtept?.toXmlString("rtept") ?: ""} """.trim().removeEmptyStrings() @@ -183,13 +184,21 @@ fun FixType.toXmlString() = """ ${this.value} """.trim().removeEmptyStrings() -fun ExtensionType.toXmlString() = """ +fun ExtensionType.toXmlString() = + if ((this.nested?.size ?: 0) > 0) { + """ + <${this.nodeName}${toXmlString(this.parameters)}>${this.nested?.toXmlString() ?: ""} + """.trim().removeEmptyStrings() + } else { + """ <${this.nodeName}${toXmlString(this.parameters)}>${this.value ?: ""} """.trim().removeEmptyStrings() + } fun TrksegType.toXmlString() = """ ${this.trkpt?.toXmlString("trkpt") ?: ""} + ${this.extensions?.toXmlString() ?: ""} """.trim().removeEmptyStrings() @@ -197,9 +206,17 @@ fun List.toXmlString(nodeName: String?) = this.joinToString(prefix = "\ it.toXmlString(nodeName) } -fun List.toXmlString() = this.joinToString( - prefix = "\n", postfix = "\n", separator = "\n", transform = ExtensionType::toXmlString -) +fun List.toXmlString(inGroup: Boolean = false): String { + if (inGroup) { + return this.joinToString( + prefix = "\n", postfix = "\n", separator = "\n", transform = ExtensionType::toXmlString + ) + } else { + return this.joinToString( + prefix = "\n", postfix = "\n", separator = "\n", transform = ExtensionType::toXmlString + ) + } +} @JvmName("toXmlStringWptType") fun List.toXmlString() = this.joinToString(prefix = "", postfix = "", separator = "") { diff --git a/src/test/kotlin/me/bvn13/sdk/android/gpx/GpxReaderTest.kt b/src/test/kotlin/me/bvn13/sdk/android/gpx/GpxReaderTest.kt index a63057d..6c253f9 100644 --- a/src/test/kotlin/me/bvn13/sdk/android/gpx/GpxReaderTest.kt +++ b/src/test/kotlin/me/bvn13/sdk/android/gpx/GpxReaderTest.kt @@ -1,5 +1,6 @@ package me.bvn13.sdk.android.gpx +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import java.time.* @@ -409,4 +410,16 @@ class GpxReaderTest { val gpx = GpxType.read(gpxString.byteInputStream()) assertEquals(gpxType, gpx) } + + @DisplayName("Read test.gpx (generated in OsmAnd Android application") + @Test + fun readTestGpx() { + val gpxType = GpxType.read(javaClass.classLoader.getResource("test.gpx").openStream()) + Assertions.assertEquals(1011, gpxType.trk?.get(0)?.trkseg?.get(0)?.trkpt?.size ?: 0) + Assertions.assertEquals(1, gpxType.trk?.get(0)?.trkseg?.get(0)?.trkpt?.get(0)?.extensions?.size ?: 0) + Assertions.assertEquals(2, gpxType.trk?.get(0)?.trkseg?.get(0)?.extensions?.nested?.size ?: 0) + Assertions.assertEquals(223, gpxType.trk?.get(0)?.trkseg?.get(0)?.extensions?.nested?.get(0)?.nested?.size ?: 0) + Assertions.assertEquals(159, gpxType.trk?.get(0)?.trkseg?.get(0)?.extensions?.nested?.get(1)?.nested?.size ?: 0) + Assertions.assertEquals(1, gpxType.extensions?.nested?.size ?: 0) + } } \ No newline at end of file diff --git a/src/test/kotlin/me/bvn13/sdk/android/gpx/ReadWriteTest.kt b/src/test/kotlin/me/bvn13/sdk/android/gpx/ReadWriteTest.kt new file mode 100644 index 0000000..9600ed5 --- /dev/null +++ b/src/test/kotlin/me/bvn13/sdk/android/gpx/ReadWriteTest.kt @@ -0,0 +1,243 @@ +package me.bvn13.sdk.android.gpx + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import java.io.ByteArrayInputStream +import java.time.* + +class ReadWriteTest { + + @DisplayName("Read-Write test") + @Test + fun testReadWrite() { + val clock = Clock.fixed( + LocalDateTime.of(2022, 9, 24, 15, 4, 0, 0).toInstant(ZoneOffset.ofHours(3)), ZoneId.of("Europe/Moscow") + ) + + val gpxType = GpxType( + MetadataType("test name", description = "test description", authorName = "bvn13"), + wpt = listOf( + WptType( + lat = 14.64736838389662, + lon = 7.93212890625, + ele = 10.toDouble(), + time = OffsetDateTime.now(clock), + magvar = 3.toDouble(), + geoidheight = 45.toDouble(), + name = "test point 1", + cmt = "comment 1", + desc = "description of point 1", + link = listOf( + LinkType( + href = "http://link-to.site.href", + text = "text", + type = "hyperlink" + ), + LinkType( + href = "http://link2-to.site.href", + text = "text2", + type = "hyperlink2" + ) + ), + src = "source 1", + sym = "sym 1", + type = "type 1", + fix = FixType.DGPS, + sat = 1, + hdop = 55.toDouble(), + vdop = 66.toDouble(), + pdop = 77.toDouble(), + ageofgpsdata = 44, + dgpsid = 88, + extensions = listOf( + ExtensionType( + "extension1", + parameters = mapOf(Pair("first", "second"), Pair("third", "fours")) + ), + ExtensionType( + "extension2", + parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd")) + ) + ) + ) + ), + rte = listOf( + RteType( + name = "rte name", + cmt = "cmt", + desc = "desc", + src = "src", + link = listOf( + LinkType( + href = "https://new.link.rte", + text = "new text rte", + type = "hyperlink" + ) + ), + number = 1234, + type = "route", + extensions = listOf( + ExtensionType( + "ext-1", + value = "value1" + ) + ), + rtept = listOf( + WptType( + lat = 14.64736838389662, + lon = 7.93212890625, + ele = 10.toDouble(), + time = OffsetDateTime.now(clock), + magvar = 3.toDouble(), + geoidheight = 45.toDouble(), + name = "test point 1", + cmt = "comment 1", + desc = "description of point 1", + link = listOf( + LinkType( + href = "http://link-to.site.href", + text = "text", + type = "hyperlink" + ), + LinkType( + href = "http://link2-to.site.href", + text = "text2", + type = "hyperlink2" + ) + ), + src = "source 1", + sym = "sym 1", + type = "type 1", + fix = FixType.DGPS, + sat = 1, + hdop = 55.toDouble(), + vdop = 66.toDouble(), + pdop = 77.toDouble(), + ageofgpsdata = 44, + dgpsid = 88, + extensions = listOf( + ExtensionType( + "extension1", + parameters = mapOf(Pair("first", "second"), Pair("third", "fours")) + ), + ExtensionType( + "extension2", + parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd")) + ) + ) + ) + ) + ) + ), + trk = listOf( + TrkType( + name = "track 1", + cmt = "comment track 1", + desc = "desc track 1", + src = "src track 1", + number = 1234, + type = "type 1", + trkseg = listOf( + TrksegType( + listOf( + WptType( + lat = 14.64736838389662, + lon = 7.93212890625, + ele = 10.toDouble(), + time = OffsetDateTime.now(clock), + magvar = 3.toDouble(), + geoidheight = 45.toDouble(), + name = "test point 1", + cmt = "comment 1", + desc = "description of point 1", + link = listOf( + LinkType( + href = "http://link-to.site.href", + text = "text", + type = "hyperlink" + ), + LinkType( + href = "http://link2-to.site.href", + text = "text2", + type = "hyperlink2" + ) + ), + src = "source 1", + sym = "sym 1", + type = "type 1", + fix = FixType.DGPS, + sat = 1, + hdop = 55.toDouble(), + vdop = 66.toDouble(), + pdop = 77.toDouble(), + ageofgpsdata = 44, + dgpsid = 88, + extensions = listOf( + ExtensionType( + "extension1", + parameters = mapOf(Pair("first", "second"), Pair("third", "fours")) + ), + ExtensionType( + "extension2", + parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd")) + ) + ) + ), + WptType( + lat = 14.64736838389662, + lon = 7.93212890625, + ele = 10.toDouble(), + time = OffsetDateTime.now(clock), + magvar = 3.toDouble(), + geoidheight = 45.toDouble(), + name = "test point 1", + cmt = "comment 1", + desc = "description of point 1", + link = listOf( + LinkType( + href = "http://link-to.site.href", + text = "text", + type = "hyperlink" + ), + LinkType( + href = "http://link2-to.site.href", + text = "text2", + type = "hyperlink2" + ) + ), + src = "source 1", + sym = "sym 1", + type = "type 1", + fix = FixType.DGPS, + sat = 1, + hdop = 55.toDouble(), + vdop = 66.toDouble(), + pdop = 77.toDouble(), + ageofgpsdata = 44, + dgpsid = 88, + extensions = listOf( + ExtensionType( + "extension1", + parameters = mapOf(Pair("first", "second"), Pair("third", "fours")) + ), + ExtensionType( + "extension2", + parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd")) + ) + ) + ) + ) + ) + ) + ) + ) + ) + + val gpx = gpxType.toXmlString(clock) + val deserializedGpxType = GpxType.read(ByteArrayInputStream(gpx.toByteArray())) + + Assertions.assertEquals(gpxType, deserializedGpxType) + } + +} \ No newline at end of file diff --git a/src/test/resources/test.gpx b/src/test/resources/test.gpx new file mode 100644 index 0000000..3632d0f --- /dev/null +++ b/src/test/resources/test.gpx @@ -0,0 +1,6459 @@ + + + + + + + +Тестовская улица (Пресненский район), Пресненский +Тестовская улица (Пресненский район), Пресненский + + +2022-09-01_15-39_Thu + + +159 + +3.6 + + + +159.2 + +3.6 + + + +159 + +3.6 + + + +160 + +3.6 + + + +161 + +6.4 + + + +161 + +6.4 + + + +161 + +6.4 + + + +158.8 + +6.4 + + + +158.5 + +6.4 + + + +157.2 + +6.4 + + + +156.5 + +6.4 + + + +155.8 + +6.4 + + + +155.6 + +6.4 + + + +155.5 + +6.4 + + + +155.2 + +6.4 + + + +155 + +6.4 + + + +154.6 + +6.4 + + + +154.6 + +6.4 + + + +154.5 + +6.4 + + + +153.8 + +6.4 + + + +153.5 + +6.4 + + + +152.8 + +6.4 + + + +152.2 + +6.4 + + + +151.8 + +6.4 + + + +151.2 + +6.4 + + + +151 + +6.4 + + + +150.5 + +6.4 + + + +149.6 + +6.4 + + + +149.5 + +6.4 + + + +147 + +6.4 + + + +146 + +6.4 + + + +145.2 + +4.2 + + + +145 + +4.2 + + + +144.5 + +4.2 + + + +144 + +4.2 + + + +143 + +4.2 + + + +143 + +4.2 + + + +142.5 + +4.2 + + + +141.5 + +4.2 + + + +141 + +4.2 + + + +140.2 + +4.2 + + + +139.5 + +8.6 + + + +140 + +8.6 + + + +140.2 + +8.6 + + + +140 + +8.6 + + + +139.8 + +8.6 + + + +139.9 + +8.6 + + + +140 + +8.6 + + + +139.8 + +8.6 + + + +139 + +4.2 + + + +137 + +8.6 + + + +136.8 + +8.6 + + + +136.2 + +8.6 + + + +136 + +8.6 + + + +134 + +8.6 + + + +134 + +8.6 + + + +134 + +8.6 + + + +134 + +8.6 + + + +134 + +8.6 + + + + +1.7 + + + +134 + +8.6 + + + +133.9 + +8.6 + + + +133.8 + +8.6 + + + +133.2 + +8.6 + + + +132.8 + +8.6 + + + +133 + +8.6 + + + +133.5 + +8.6 + + + +134 + +8.6 + + + +134.8 + +8.6 + + + +135.2 + +8.6 + + + +135.5 + +8.6 + + + +135.4 + +8.6 + + + +135.3 + +8.6 + + + +135.3 + +8.6 + + + +135 + +8.6 + + + +135.8 + +8.6 + + + +136 + +8.6 + + + +137 + +8.6 + + + +137 + +8.6 + + + +137 + +8.6 + + + +137 + +8.6 + + + +137 + +8.6 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + +140 + +1.4 + + + +139.8 + +1.4 + + + + +4.2 + + + +141 + +4.2 + + + +141 + +1.4 + + + +141 + +4.2 + + + +141.1 + +4.2 + + + +141.2 + +4.2 + + + +141.5 + +4.2 + + + +142.2 + +4.2 + + + +142 + +4.2 + + + +142.8 + +4.2 + + + +142.9 + +6.4 + + + +142.8 + +6.4 + + + +142.8 + +6.4 + + + +143 + +6.4 + + + +143.2 + +6.4 + + + +143.2 + +6.4 + + + +144.1 + +6.4 + + + +144.3 + +6.4 + + + +144.5 + +6.4 + + + +144 + +6.4 + + + +143 + +6.4 + + + +143.8 + +6.4 + + + +143.5 + +6.4 + + + +142.2 + +6.4 + + + +140.2 + +6.4 + + + +140 + +6.4 + + + +139.2 + +6.4 + + + +139.5 + +6.4 + + + +139.8 + +6.4 + + + +140.2 + +6.4 + + + +140.8 + +6.4 + + + +144.5 + +6.4 + + + +145 + +6.4 + + + +143.3 + +6.4 + + + +143 + +6.4 + + + +142.5 + +6.4 + + + +141.8 + +6.4 + + + +141.2 + +6.4 + + + +140.3 + +6.4 + + + +140 + +6.4 + + + +140.8 + +6.4 + + + +140.2 + +6.4 + + + +141 + +3.6 + + + +141 + +3.6 + + + +143.2 + +3.6 + + + +143.8 + +4.2 + + + +144 + +4.2 + + + +144 + +5.3 + + + +145.5 + +6.4 + + + +146.2 + +6.4 + + + +146.8 + +6.4 + + + +146.9 + +6.4 + + + +147 + +6.4 + + + +146.8 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147.6 + +6.4 + + + +147.8 + +6.4 + + + +147.8 + +6.4 + + + +147.9 + +6.4 + + + +147.9 + +6.4 + + + +148 + +6.4 + + + +148 + +6.4 + + + +148 + +6.4 + + + +148 + +6.4 + + + +147.7 + +6.4 + + + +147.6 + +6.4 + + + +147.5 + +6.4 + + + +147.5 + +6.4 + + + +146.5 + +6.4 + + + +146 + +6.4 + + + +144 + +6.4 + + + +143.2 + +6.4 + + + +142.5 + +6.4 + + + +141 + +6.4 + + + +140 + +3.1 + + + +139 + +5.3 + + + +137.2 + +2.8 + + + +136.8 + +2.8 + + + +136.5 + +2.8 + + + +136.8 + +4.2 + + + +136.1 + +4.2 + + + + +4.2 + + + +136 + +4.2 + + + +136.5 + +4.2 + + + +137 + +6.4 + + + +139 + +6.4 + + + +139.5 + +6.4 + + + +140 + +6.4 + + + +141.5 + +6.4 + + + +142 + +6.4 + + + +144.2 + +6.4 + + + +145 + +6.4 + + + +145.1 + +6.4 + + + +145.2 + +6.4 + + + +145 + +5.6 + + + +145.2 + +5.6 + + + +145.2 + +5.6 + + + +145 + +5.6 + + + +145 + +5.6 + + + +144 + +5.6 + + + +144.5 + +5.6 + + + +144.8 + +5.6 + + + +145.2 + +5.6 + + + +145 + +5.6 + + + +144.8 + +5.6 + + + +144.8 + +5.6 + + + +144.8 + +5.6 + + + +144.5 + +5.6 + + + +144.2 + +5.6 + + + +142.8 + +5.6 + + + +143.2 + +5.6 + + + +143.8 + +5.6 + + + +144.2 + +5.6 + + + +144.8 + +5.6 + + + +144.4 + +5.6 + + + +144.3 + +5.6 + + + +144.1 + +5.6 + + + +144 + +5.6 + + + +144 + +5.6 + + + +143.5 + +5.6 + + + +143 + +5.6 + + + +142 + +3.6 + + + +142.2 + +3.6 + + + +142.1 + +3.6 + + + +142 + +3.6 + + + +142 + +5.3 + + + +141.9 + +5.3 + + + +141.8 + +5.3 + + + +140.8 + +5.3 + + + +139.8 + +5.3 + + + +138.2 + +5.3 + + + +137.8 + +5.3 + + + +137.2 + +5.3 + + + +136 + +5.3 + + + +136 + +5.3 + + + +135.5 + +5.3 + + + +135 + +5.3 + + + +135.8 + +5.3 + + + +136 + +5.3 + + + +136 + +5.3 + + + +136 + +4.2 + + + +135.5 + +4.2 + + + +135.4 + +4.2 + + + +135.2 + +4.2 + + + +135 + +4.2 + + + +135 + +4.2 + + + +135.2 + +4.2 + + + +136 + +4.2 + + + +137.5 + +4.2 + + + +137.7 + +4.2 + + + +137.9 + +4.2 + + + +138 + +4.2 + + + +138 + +4.2 + + + +138.5 + +4.2 + + + +138.9 + +4.2 + + + +139 + +4.2 + + + +138.8 + +4.2 + + + +138 + +5.3 + + + +139.1 + +6.4 + + + +139.2 + +6.4 + + + +140.2 + +6.4 + + + +140.5 + +6.4 + + + +140.8 + +6.4 + + + +141.2 + +6.4 + + + +141.2 + +6.4 + + + +141.5 + +6.4 + + + +143.6 + +6.4 + + + +143.9 + +6.4 + + + +144 + +6.4 + + + +144.5 + +6.4 + + + +144.4 + +6.4 + + + +144.2 + +6.4 + + + +144 + +6.4 + + + +143.8 + +6.4 + + + +144 + +6.4 + + + +144 + +6.4 + + + +145 + +6.4 + + + +146 + +6.4 + + + +146.8 + +6.4 + + + +146.9 + +6.4 + + + +147 + +6.4 + + + +147 + +6.4 + + + +147.4 + +6.4 + + + +147.7 + +6.4 + + + +147.7 + +6.4 + + + +147.8 + +6.4 + + + +148 + +6.4 + + + +149.2 + +6.4 + + + +151 + +6.4 + + + +152.8 + +6.4 + + + +153 + +6.4 + + + +153.2 + +6.4 + + + +153.6 + +6.4 + + + +153.6 + +6.4 + + + +153.7 + +6.4 + + + +153.7 + +6.4 + + + +153.8 + +6.4 + + + +154 + +6.4 + + + +154 + +6.4 + + + +154.2 + +6.4 + + + +155 + +3.1 + + + +155.2 + +3.1 + + + +155.8 + +3.1 + + + +156.5 + +3.1 + + + +158.2 + +6.7 + + + +158.2 + +6.7 + + + +158.3 + +6.7 + + + +158.3 + +6.7 + + + +158.4 + +6.7 + + + +158.6 + +6.7 + + + +158.7 + +6.7 + + + +158.8 + +6.7 + + + +158.9 + +6.7 + + + +158.9 + +6.7 + + + +159 + +6.7 + + + +159.1 + +6.7 + + + +159.2 + +6.7 + + + +159.7 + +6.7 + + + +159.8 + +6.7 + + + +159.8 + +6.7 + + + +159.8 + +6.7 + + + +159.9 + +6.7 + + + +159.9 + +6.7 + + + +160 + +6.7 + + + +160.2 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.3 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.6 + +6.7 + + + +160.6 + +6.7 + + + +160.6 + +6.7 + + + +160.7 + +6.7 + + + +160.7 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +161 + +6.7 + + + +161 + +6.7 + + + +160.9 + +6.7 + + + +160.8 + +6.7 + + + +160.7 + +6.7 + + + +160.6 + +6.7 + + + +160.4 + +6.7 + + + +160 + +6.7 + + + +160.8 + +6.7 + + + +160.8 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +161 + +6.7 + + + +160.8 + +6.7 + + + +160.6 + +6.7 + + + +160.5 + +6.7 + + + +160.5 + +6.7 + + + +160.4 + +6.7 + + + +160.3 + +6.7 + + + +160.2 + +6.7 + + + +160 + +6.7 + + + +159.8 + +6.7 + + + +159.7 + +6.7 + + + +159.6 + +6.7 + + + +159.5 + +6.7 + + + +159.8 + +6.7 + + + +160 + +6.7 + + + +160.2 + +6.7 + + + +160 + +6.7 + + + +160.2 + +6.7 + + + +160 + +6.7 + + + +160 + +6.7 + + + +160.1 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.2 + +6.7 + + + +160.4 + +6.7 + + + +160.4 + +6.7 + + + +160.5 + +6.7 + + + +160.8 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +160.9 + +6.7 + + + +161 + +6.7 + + + +161 + +6.7 + + + +161.2 + +6.7 + + + +161.5 + +6.7 + + + +161.8 + +6.7 + + + +161.8 + +6.7 + + + +161.9 + +6.7 + + + +161.9 + +6.7 + + + +161.9 + +6.7 + + + +162 + +6.7 + + + +162.5 + +4.2 + + + +162.8 + +4.2 + + + +163 + +4.2 + + + +163.1 + +4.2 + + + +163.2 + +4.2 + + + +163.2 + +4.2 + + + +163.2 + +4.2 + + + +163.2 + +4.2 + + + +163.2 + +4.2 + + + +164 + +4.2 + + + +164.8 + +4.2 + + + +164.5 + +4.2 + + + +164.2 + +4.2 + + + +164.1 + +4.2 + + + +164.9 + +4.2 + + + +164.9 + +4.2 + + + +164.9 + +4.2 + + + +165 + +4.2 + + + +165 + +4.2 + + + +164.9 + +4.2 + + + +164.2 + +4.2 + + + +164 + +4.2 + + + +164 + +4.2 + + + +164 + +4.2 + + + +163.1 + +4.2 + + + +163 + +4.2 + + + +162 + +4.2 + + + +162.2 + +4.2 + + + +162.5 + +4.2 + + + +163 + +6.4 + + + +163 + +6.4 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +6.4 + + + +162 + +5 + + + +162.1 + +5 + + + +162.2 + +5 + + + +163 + +5 + + + +163.1 + +5 + + + +164 + +5 + + + +163.8 + +5 + + + +163 + +5 + + + +163.5 + +5 + + + +164 + +5 + + + +163.8 + +5 + + + +163 + +5 + + + +163.1 + +5 + + + +163.1 + +5 + + + +163.2 + +5 + + + +163.3 + +5 + + + +163.4 + +5 + + + +163.8 + +5 + + + +164 + +5 + + + +164 + +5 + + + +164 + +5 + + + +163 + +5 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +4.2 + + + +163 + +1.4 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + + +4.2 + + + +163 + +1.4 + + + +164 + +4.2 + + + +164 + +4.2 + + + +164 + +4.2 + + + +164 + +4.2 + + + +164.2 + +6.4 + + + +163.5 + +6.4 + + + +163.5 + +6.4 + + + +163.4 + +6.4 + + + +163.4 + +6.4 + + + +163.4 + +6.4 + + + +163.4 + +6.4 + + + +163.4 + +6.4 + + + +163.2 + +6.4 + + + +163.1 + +6.4 + + + +163.1 + +6.4 + + + +163 + +6.4 + + + +162.5 + +6.4 + + + +162.3 + +6.4 + + + +162.2 + +6.4 + + + +162.1 + +6.4 + + + +162 + +3.6 + + + +163 + +3.6 + + + +163.8 + +3.6 + + + +164 + +3.1 + + + +164 + +4.2 + + + +165.8 + +4.2 + + + +166.2 + +4.2 + + + +166.3 + +4.2 + + + +166 + +4.2 + + + +166.8 + +4.2 + + + +165.8 + +4.2 + + + +165 + +4.2 + + + +164.9 + +4.2 + + + +165 + +4.2 + + + +164.8 + +4.2 + + + +164 + +6.4 + + + +164 + +6.4 + + + +164 + +6.4 + + + +164.5 + +6.4 + + + +165.2 + +6.4 + + + +165.7 + +6.4 + + + +166.2 + +6.4 + + + +166.3 + +6.4 + + + +166.4 + +6.4 + + + +166.4 + +6.4 + + + +167.2 + +6.4 + + + +167.2 + +6.4 + + + +167.2 + +6.4 + + + +167 + +6.4 + + + +167 + +6.4 + + + +167 + +6.4 + + + +168 + +6.4 + + + +168.2 + +6.4 + + + +168.5 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168.2 + +6.4 + + + +168.5 + +6.4 + + + +168.7 + +6.4 + + + +168 + +3.1 + + + +168.2 + +4.2 + + + +168 + +4.2 + + + +167.8 + +4.2 + + + +167.7 + +4.2 + + + +167.6 + +4.2 + + + +167.6 + +4.2 + + + +167.6 + +4.2 + + + +167.5 + +4.2 + + + +167.5 + +4.2 + + + +167.5 + +4.2 + + + +167.4 + +4.2 + + + +167.4 + +4.2 + + + +167.3 + +4.2 + + + +167.3 + +4.2 + + + +167.3 + +4.2 + + + +167.3 + +4.2 + + + +167.2 + +4.2 + + + +167.2 + +4.2 + + + +167.2 + +4.2 + + + +167.1 + +4.2 + + + +167.1 + +4.2 + + + +167.1 + +4.2 + + + +167 + +1.4 + + + +167 + +4.2 + + + +168 + +4.2 + + + +167.7 + +4.2 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +167.2 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +168 + +6.4 + + + +169 + +6.4 + + + +169 + +6.4 + + + +169 + +6.4 + + + +169.1 + +6.4 + + + +169.2 + +6.4 + + + +169.2 + +6.4 + + + +169.2 + +6.4 + + + +169.7 + +6.4 + + + +169.8 + +6.4 + + + +169.8 + +6.4 + + + +169.8 + +6.4 + + + +169.9 + +6.4 + + + +170 + +6.4 + + + +170 + +6.4 + + + +170.2 + +6.4 + + + +170 + +6.4 + + + +169.8 + +6.4 + + + +169 + +6.4 + + + +168.5 + +6.4 + + + +168 + +6.4 + + + +167.5 + +6.4 + + + +167.2 + +6.4 + + + +167.1 + +6.4 + + + +167 + +6.4 + + + +167 + +6.4 + + + +166.9 + +6.4 + + + +166.8 + +6.4 + + + +166.3 + +6.4 + + + +166.2 + +6.4 + + + +166 + +6.4 + + + +166.1 + +6.4 + + + +167 + +4.2 + + + +167 + +4.2 + + + +167 + +4.2 + + + +167 + +4.2 + + + +167 + +4.2 + + + +166.2 + +4.2 + + + +166.1 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +166 + +4.2 + + + +165 + +4.2 + + + +165 + +4.2 + + + +166 + +4.2 + + + +165.3 + +4.2 + + + +165 + +4.2 + + + +165.1 + +4.2 + + + +165.2 + +4.2 + + + +165.2 + +4.2 + + + +165 + +4.2 + + + +165 + +4.2 + + + +165 + +4.2 + + + +166 + +4.2 + + + +167 + +4.2 + + + +166.5 + +4.2 + + + +166.2 + +4.2 + + + +167 + +4.2 + + + +168 + +4.2 + + + +168 + +4.2 + + + +168.1 + +4.2 + + + +168.1 + +4.2 + + + +168.1 + +4.2 + + + +168.1 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168.2 + +4.2 + + + +168 + +4.2 + + + +167.9 + +4.2 + + + +167.8 + +4.2 + + + +167.8 + +4.2 + + + +167.8 + +4.2 + + + +167.8 + +4.2 + + + +167.5 + +6.4 + + + +167.2 + +6.4 + + + +168 + +6.4 + + + +168.3 + +6.4 + + + +168.5 + +6.4 + + + +168.5 + +6.4 + + + +169 + +6.4 + + + +168.9 + +6.4 + + + +168.6 + +6.4 + + + +168.5 + +6.4 + + + +168.2 + +6.4 + + + +167 + +6.4 + + + +165.2 + +6.4 + + + +162.3 + +6.4 + + + +162.2 + +6.4 + + + +161.5 + +6.4 + + + +161.2 + +6.4 + + + +161 + +6.4 + + + +161.2 + +6.4 + + + +161 + +6.4 + + + +160.9 + +6.4 + + + +160.8 + +6.4 + + + +160.8 + +6.4 + + + +160.5 + +6.4 + + + +160.2 + +6.4 + + + +160.1 + +6.4 + + + +159.8 + +6.4 + + + +160 + +6.4 + + + +160.4 + +6.4 + + + +160.4 + +6.4 + + + +160.5 + +6.4 + + + +160.5 + +6.4 + + + +160.8 + +6.4 + + + +160.6 + +6.4 + + + +160.5 + +6.4 + + + +160.5 + +6.4 + + + +159.5 + +6.4 + + + +159 + +6.4 + + + +158.8 + +6.4 + + + +158.7 + +6.4 + + + +158.7 + +6.4 + + + +158.7 + +6.4 + + + +158.6 + +6.4 + + + +158.6 + +6.4 + + + +158.6 + +6.4 + + + +158.6 + +6.4 + + + +158.5 + +6.4 + + + +158.5 + +6.4 + + + +158.8 + +6.4 + + + +159.2 + +6.4 + + + +159.4 + +6.4 + + + +159.5 + +6.4 + + + +160.5 + +6.4 + + + +159.8 + +4.2 + + + +160 + +4.2 + + + +160 + +4.2 + + + +159.8 + +4.2 + + + +159.7 + +4.2 + + + +159.7 + +4.2 + + + +159.7 + +4.2 + + + +159.6 + +4.2 + + + +159.5 + +4.2 + + + +159.5 + +4.2 + + + +159.2 + +4.2 + + + +159.2 + +4.2 + + + +159.2 + +4.2 + + + +159.1 + +4.2 + + + +159.1 + +4.2 + + + +159.1 + +4.2 + + + +159.2 + +4.2 + + + +159 + +4.2 + + + +159 + +1.4 + + + +159 + +4.2 + + + +159 + +1.4 + + + +159 + +4.2 + + + + +4.2 + + + +158 + +4.2 + + + +158 + +1.4 + + + +158 + +4.2 + + + +158 + +4.2 + + + +158 + +1.4 + + + +157 + +4.2 + + + +157 + +1.4 + + + +157 + +4.2 + + + +157.4 + +4.2 + + + +157 + +4.2 + + + +158 + +4.2 + + + +158 + +4.2 + + + +158 + +4.2 + + + +157.9 + +4.2 + + + +157.9 + +4.2 + + + +157.9 + +4.2 + + + +157.8 + +4.2 + + + +157.8 + +4.2 + + + +157.8 + +4.2 + + + +157.7 + +4.2 + + + +157.5 + +4.2 + + + +157 + +4.2 + + + +157 + +4.2 + + + +157 + +4.2 + + + +157 + +4.2 + + + +157.1 + +4.2 + + + +157.3 + +4.2 + + + +157.8 + +4.2 + + + +158.2 + +4.2 + + + +157 + +4.2 + + + +156.9 + +4.2 + + + +156.8 + +4.2 + + + +155 + +4.2 + + + +154.5 + +4.2 + + + +154 + +4.2 + + + +152.8 + +4.2 + + + +152.6 + +4.2 + + + +152.5 + +4.2 + + + +152.5 + +4.2 + + + +152.5 + +4.2 + + + +152.4 + +4.2 + + + +152.4 + +4.2 + + + +152.2 + +4.2 + + + +151.8 + +4.2 + + + +152.5 + +4.2 + + + +152.4 + +4.2 + + + +152.3 + +4.2 + + + +152.2 + +4.2 + + + +152 + +4.2 + + + +151.8 + +4.2 + + + +152 + +4.2 + + + +152.1 + +4.2 + + + +152.1 + +4.2 + + + +152.2 + +4.2 + + + +152.2 + +4.2 + + + +152.2 + +4.2 + + + +152.3 + +4.2 + + + +152.3 + +4.2 + + + +152.4 + +4.2 + + + +152.4 + +4.2 + + + +152.8 + +4.2 + + + +152.8 + +4.2 + + + +153.1 + +4.2 + + + +154.2 + +4.2 + + + +154.4 + +4.2 + + + +154.5 + +4.2 + + + +153.8 + +4.2 + + + +155 + +4.2 + + + +155 + +4.2 + + + +154.9 + +4.2 + + + +154.6 + +4.2 + + + +154.4 + +4.2 + + + +154.2 + +4.2 + + + +154.2 + +4.2 + + + +154 + +4.2 + + + +153.8 + +4.2 + + + +153 + +4.2 + + + +152.5 + +4.2 + + + +152.2 + +4.2 + + + +152.2 + +4.2 + + + +152.1 + +4.2 + + + +152.1 + +4.2 + + + +152 + +4.2 + + + +152.1 + +4.2 + + + +152.1 + +4.2 + + + +152.2 + +4.2 + + + +152 + +4.2 + + + +152 + +4.2 + + + +153 + +4.2 + + + +153.2 + +4.2 + + + +153.2 + +4.2 + + + +153.2 + +4.2 + + + +153.6 + +4.2 + + + +153.7 + +4.2 + + + +153.7 + +4.2 + + + +153.7 + +4.2 + + + +154 + +4.2 + + + +154.2 + +4.2 + + + +154.8 + +4.2 + + + +154.9 + +4.2 + + + +155 + +4.2 + + + +154.2 + +4.2 + + + +154.2 + +4.2 + + + +154.1 + +4.2 + + + +154 + +4.2 + + + +153 + +4.2 + + + +153 + +4.2 + + + +152.8 + +4.2 + + + +152.8 + +4.2 + + + +152.8 + +4.2 + + + +152.2 + +4.2 + + + +152 + +4.2 + + + +151 + +4.2 + + + +151 + +4.2 + + + +151 + +4.2 + + + +152.1 + +4.2 + + + +152.2 + +4.2 + + + +152.6 + +4.2 + + + +153 + +4.2 + + + +153 + +4.2 + + + +153 + +4.2 + + + +153 + +4.2 + + + +153.1 + +4.2 + + + +152.5 + +4.2 + + + +154.2 + +4.2 + + + +154 + +4.2 + + + +153 + +4.2 + + + +152.5 + +4.2 + + + +150 + +4.2 + + + +148.2 + +4.2 + + + +146.8 + +4.2 + + + +146 + +1.4 + + + +146.1 + +4.2 + + + +145.8 + +1.4 + + + +146 + +1.4 + + + +146.2 + +4.2 + + + +146 + +4.2 + + + +146 + +4.2 + + + +146 + +4.2 + + + +146.8 + +4.2 + + + +146.5 + +4.2 + + + +146.2 + +4.2 + + + +145 + +4.2 + + + +143.8 + +6.4 + + + +142.8 + +6.4 + + + +139.5 + +6.4 + + + +136.8 + +6.4 + + + +136.2 + +6.4 + + + +136.1 + +6.4 + + + +136 + +5 + + + +137 + +3.1 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +137 + +4.2 + + + +135.8 + +4.2 + + + +134.2 + +4.2 + + + +134.1 + +4.2 + + + +134 + +4.2 + + + +134 + +4.2 + + + +134 + +4.2 + + + +133.8 + +4.2 + + + +133.5 + +4.2 + + + +133.5 + +4.2 + + + +133.4 + +4.2 + + + +133.4 + +4.2 + + + +133.3 + +4.2 + + + +133.3 + +4.2 + + + +133.3 + +4.2 + + + +133.3 + +4.2 + + + +133.2 + +4.2 + + + +133.8 + +4.2 + + + +133.5 + +4.2 + + + +133.2 + +4.2 + + + +133 + +4.2 + + + +132.8 + +4.2 + + + +132.5 + +4.2 + + + +132 + +4.2 + + + +131.1 + +4.2 + + + +130.9 + +4.2 + + + +130.8 + +4.2 + + + +130.7 + +4.2 + + + +130.6 + +4.2 + + + +130.5 + +4.2 + + + +130.8 + +4.2 + + + +131.5 + +4.2 + + + +131.5 + +4.2 + + + +131 + +4.2 + + + +130.8 + +4.2 + + + +129.8 + +4.2 + + + +128.8 + +4.2 + + + +128 + +4.2 + + + +127.8 + +4.2 + + + +128.2 + +4.2 + + + +128.2 + +4.2 + + + +128 + +4.2 + + + +128.2 + +4.2 + + + +130 + +4.2 + + + +130 + +4.2 + + + +130.2 + +4.2 + + + +130 + +1.4 + + + + +4.2 + + + + +4.2 + + + +130 + +1.4 + + + +129 + +4.2 + + + +129.8 + +4.2 + + + +130 + +4.2 + + + +130.2 + +4.2 + + + +130.5 + +4.2 + + + +130.8 + +4.2 + + + +130.9 + +4.2 + + + +131 + +4.2 + + + +131.3 + +4.2 + + + +131.6 + +4.2 + + + +131.7 + +4.2 + + + +132 + +4.2 + + + +131.8 + +4.2 + + + +131.4 + +4.2 + + + +131.4 + +4.2 + + + +131.3 + +4.2 + + + +131.2 + +4.2 + + + +131 + +4.2 + + + +131 + +4.2 + + + +130 + +4.2 + + + +129.8 + +4.2 + + + +129.6 + +4.2 + + + +129.5 + +4.2 + + + +129.2 + +4.2 + + + +129.1 + +4.2 + + + +129.1 + +4.2 + + + +129.1 + +4.2 + + + +129 + +4.2 + + + +129 + +4.2 + + + +128.9 + +4.2 + + + +128.8 + +4.2 + + + +128.5 + +4.2 + + + +128.8 + +4.2 + + + +129 + +4.2 + + + +129 + +4.2 + + + +129 + +4.2 + + + +128.5 + +4.2 + + + +128 + +4.2 + + + +127.8 + +4.2 + + + +128 + +4.2 + + + +127 + +4.2 + + + +126.8 + +4.2 + + + +126.2 + +4.2 + + + +125.8 + +4.2 + + + +125.7 + +4.2 + + + +125.6 + +4.2 + + + +125.6 + +4.2 + + + +125.5 + +4.2 + + + +125.4 + +4.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +