Chapter Introduction

Welcome to Chapter 10! So far, we’ve meticulously built a robust Mermaid code analyzer, validator, and fixer with a strong emphasis on correctness and maintainability. Our lexer, parser, AST, and rule engine are designed to be strict and deterministic. However, as diagrams grow in complexity and size, performance and memory footprint become critical concerns, especially for a production-grade CLI tool that might process thousands of lines of Mermaid code or be integrated into CI/CD pipelines.

In this chapter, we will shift our focus to optimizing the performance of our mermaid-tool and enabling it to handle large input files efficiently through streaming. We’ll explore techniques like zero-copy parsing, arena allocation for our Abstract Syntax Tree (AST), and leveraging Rust’s io::Read and BufReader for streaming input. The goal is to achieve near-linear parsing complexity with minimal memory allocations, ensuring our tool remains fast and resource-efficient even with very large Mermaid diagrams.

By the end of this chapter, you will have a mermaid-tool that not only correctly processes and validates Mermaid code but also does so with high performance and low memory consumption, capable of handling streaming input without loading entire files into memory. We will also set up a robust benchmarking framework to measure and track our performance improvements.

Planning & Design

Optimizing for performance often involves trade-offs. Our primary goals are speed (low CPU time) and memory efficiency (low RAM usage). For a compiler-like tool, the lexing and parsing phases are typically the most performance-sensitive.

Performance Bottlenecks & Strategies

  1. Input Reading: Reading large files entirely into memory can be slow and consume excessive RAM.
    • Strategy: Use std::io::BufReader to read input in chunks. This allows us to process files larger than available memory and reduces syscall overhead.
  2. Lexing (Tokenization): Frequent string allocations for each token and repeated character scanning can be costly.
    • Strategy: Implement “zero-copy” lexing by having tokens refer to slices of the original input buffer (&'a str or TokenSpan) instead of allocating new strings. This requires careful lifetime management.
    • Strategy: Use optimized byte-searching functions (e.g., memchr from the memchr crate) for faster token boundary detection.
  3. Parsing & AST Construction: Each AST node often involves a heap allocation. For large ASTs, this leads to many small, scattered allocations, impacting cache locality and increasing memory overhead.
    • Strategy: Utilize an Arena allocator (e.g., bumpalo crate). An arena allocates memory in large blocks and doles out smaller chunks from it. This dramatically reduces allocation overhead, improves cache locality, and simplifies deallocation (just drop the arena). AST nodes will store references (&'a str) to strings within the arena or the original input buffer.
  4. String Handling in AST: If AST nodes own String data, there’s a lot of copying.
    • Strategy: Use Cow<'a, str> (Clone-on-Write) for string data in AST nodes. This allows borrowing a slice from the input buffer when possible, and only allocating a new String when modifications are necessary (e.g., during rule application that fixes labels).
  5. Data Structures: Using Vec can be efficient, but frequent reallocations can occur.
    • Strategy: Pre-allocate Vec capacities where reasonable (e.g., Vec::with_capacity). Consider SmallVec for cases where a Vec is typically small but might grow.

Architecture Diagram: Optimized Compiler Pipeline

Let’s visualize the optimized data flow:

flowchart TD A[Input Source: File/Stdin] --> B[BufReader] B -->|Chunked Input Stream| C{Lexer} C -->|Zero-Copy Tokens (TokenSpan)| D{Parser} D -->|AST Nodes (Arena-Allocated)| E[AST] E --> F[Validator] E --> G[Rule Engine] G --> H[Formatter] H --> I[Output: Corrected Mermaid/Diagnostics] subgraph Optimizations C -.->|memchr| C D -.->|bumpalo::Arena| D E -.->|Cow<'a, str>| E end style A fill:#f9f,stroke:#333,stroke-width:2px style I fill:#f9f,stroke:#333,stroke-width:2px style C fill:#ccf,stroke:#333,stroke-width:2px style D fill:#ccf,stroke:#333,stroke-width:2px style E fill:#ccf,stroke:#333,stroke-width:2px style F fill:#cfc,stroke:#333,stroke-width:2px style G fill:#cfc,stroke:#333,stroke-width:2px style H fill:#cfc,stroke:#333,stroke-width:2px style Optimizations fill:#eee,stroke:#999,stroke-dasharray: 5 5

File Structure Changes

We will primarily modify existing files: src/lexer.rs, src/parser.rs, and src/ast.rs. We’ll also add a new file for benchmarking.

mermaid-tool/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── ast.rs
│   ├── lexer.rs          # Modified for streaming & zero-copy
│   ├── parser.rs         # Modified for arena allocation
│   ├── diagnostics.rs
│   ├── validator.rs
│   ├── rules/
│   │   └── mod.rs
│   │   └── ...
│   ├── formatter.rs
│   └── cli.rs
└── benches/              # New directory for benchmarks
    └── parsing_benchmark.rs

Step-by-Step Implementation

1. Setup/Configuration

First, let’s add the necessary crates to our Cargo.toml: bumpalo for arena allocation, memchr for fast byte searching, and criterion for benchmarking.

Open Cargo.toml and add these dependencies:

# Cargo.toml
[dependencies]
# Existing dependencies
# ...
clap = { version = "4.5", features = ["derive"] }
miette = { version = "7.2", features = ["fancy", "supports-color"] }
thiserror = "1.0"
log = "0.4"
env_logger = "0.11"
# New dependencies for performance
bumpalo = "3.16" # For arena allocation
memchr = "2.7"   # For fast byte searching

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "parsing_benchmark"
harness = false

Explanation:

  • bumpalo: A fast, thread-local arena allocator. Ideal for ASTs where nodes have a shared lifetime.
  • memchr: Provides highly optimized routines for searching for bytes or byte sequences in memory.
  • criterion: A robust benchmarking harness for Rust. The html_reports feature generates interactive HTML reports.
  • The [[bench]] section tells Cargo about our benchmark target and disables the default test harness for it, allowing criterion to take over.

2. Core Implementation: Lexer Streaming & Zero-Copy

Our current lexer reads the entire input string. We need to refactor it to work with a BufReader and return TokenSpans that refer to the original buffer.

a) Modify src/lexer.rs - TokenSpan and Token

We’ll introduce a TokenSpan struct that holds the start and end byte indices within the input buffer. This replaces storing String directly in Token.

// src/lexer.rs

use std::borrow::Cow;
use std::fmt;
use std::io::{self, BufReader, Read};
use std::ops::Range;
use memchr::memchr; // Import memchr

/// Represents a span of bytes in the original input source.
/// This is crucial for zero-copy lexing, as tokens will refer to these spans
/// instead of owning duplicated string data.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenSpan {
    /// Start byte index (inclusive)
    pub start: usize,
    /// End byte index (exclusive)
    pub end: usize,
}

impl TokenSpan {
    /// Creates a new `TokenSpan`.
    pub fn new(start: usize, end: usize) -> Self {
        Self { start, end }
    }

    /// Returns the length of the span.
    pub fn len(&self) -> usize {
        self.end - self.start
    }

    /// Checks if the span is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Resolves the span to a string slice from the given source.
    pub fn resolve<'a>(&self, source: &'a str) -> &'a str {
        &source[self.start..self.end]
    }
}

// Existing TokenKind enum (truncated for brevity)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TokenKind {
    // Keywords
    Graph, Flowchart, Sequence, Class, State, ErDiagram, GitGraph, Gantt, Pie,
    C4Diagram, Journey, Requirement,
    // Operators/Delimiters
    ArrowLeft, ArrowRight, ArrowBoth, ArrowOpen, ArrowX,
    Colon, Semicolon, Comma, Dot,
    // Brackets
    ParenOpen, ParenClose, BracketOpen, BracketClose, CurlyOpen, CurlyClose,
    SquareOpen, SquareClose,
    // Identifiers and Literals
    Identifier,
    StringLiteral, // e.g., "This is a label"
    NumberLiteral, // e.g., 123
    // Whitespace and Comments
    Whitespace,
    Comment,
    Newline,
    // Special
    Eof,
    Invalid,
}

/// Represents a single token produced by the lexer.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Token {
    pub kind: TokenKind,
    pub span: TokenSpan, // Use TokenSpan instead of String
}

impl Token {
    pub fn new(kind: TokenKind, span: TokenSpan) -> Self {
        Self { kind, span }
    }
}

// ... (rest of the file will be modified)

Explanation:

  • TokenSpan: This struct is the core of our zero-copy strategy. Instead of Token directly holding String data, it now holds a TokenSpan which is just a pair of usize indices. This means no heap allocations are made for token values during lexing.
  • resolve: A helper method to get the actual &str slice from the original input when needed.
  • memchr: Imported for efficient byte searching.

b) Modify src/lexer.rs - Lexer struct and next_token

The Lexer struct needs to be refactored to work with a BufReader and maintain an internal buffer, and to produce Tokens with TokenSpans.

// src/lexer.rs

// ... (imports and TokenSpan, TokenKind, Token structs from above)

/// Represents a lexical error.
#[derive(Debug, Clone, PartialEq, Eq, miette::Diagnostic, thiserror::Error)]
#[error("Lexical error")]
#[diagnostic(code(mermaid::lexer::error))]
pub struct LexerError {
    #[source_code]
    pub src: miette::NamedSource,
    #[label("This character is not allowed")]
    pub bad_char_span: miette::SourceSpan,
    pub help: Option<String>,
}

/// The Lexer for Mermaid diagrams.
/// It reads from an `io::Read` source, buffers it, and produces tokens.
pub struct Lexer<R: Read> {
    reader: BufReader<R>,
    buffer: Vec<u8>, // Internal buffer for chunks of input
    cursor: usize,   // Current position within the buffer
    offset: usize,   // Total bytes read from the start of the stream
    line_start_offsets: Vec<usize>, // Store byte offsets for line beginnings
    current_line: usize,
    eof_reached: bool,
}

impl<R: Read> Lexer<R> {
    /// Creates a new Lexer instance.
    /// `source_name` is used for diagnostics.
    pub fn new(reader: R) -> Self {
        Self {
            reader: BufReader::new(reader),
            buffer: Vec::with_capacity(4096), // Initial buffer capacity
            cursor: 0,
            offset: 0,
            line_start_offsets: vec![0], // The first line starts at offset 0
            current_line: 1,
            eof_reached: false,
        }
    }

    /// Fills the internal buffer if it's empty or needs more data.
    /// Returns `true` if more data was read, `false` if EOF was reached and buffer is empty.
    fn fill_buffer(&mut self) -> io::Result<bool> {
        // If we're at the end of the current buffer, shift remaining data or clear.
        if self.cursor >= self.buffer.len() {
            self.buffer.clear();
            self.cursor = 0;
            // Attempt to read more data
            let bytes_read = self.reader.read_to_end(&mut self.buffer)?;
            if bytes_read == 0 {
                self.eof_reached = true;
                return Ok(false); // EOF reached and buffer is now empty
            }
            Ok(true)
        } else {
            // Keep existing data, perhaps shift it to the beginning if it's a small remainder
            // For now, a simpler strategy: if we need more data and buffer is not full, read more.
            // This could be optimized later to shift only if needed.
            Ok(true) // Buffer still has data
        }
    }

    /// Peeks at the byte at the current cursor position.
    /// Returns `Some(byte)` if available, `None` if EOF.
    fn peek(&mut self) -> io::Result<Option<u8>> {
        self.fill_buffer()?;
        if self.cursor < self.buffer.len() {
            Ok(Some(self.buffer[self.cursor]))
        } else {
            Ok(None)
        }
    }

    /// Consumes the byte at the current cursor position and advances the cursor.
    /// Returns `Some(byte)` if available, `None` if EOF.
    fn consume(&mut self) -> io::Result<Option<u8>> {
        self.fill_buffer()?;
        if self.cursor < self.buffer.len() {
            let byte = self.buffer[self.cursor];
            self.cursor += 1;
            self.offset += 1; // Update total offset
            Ok(Some(byte))
        } else {
            Ok(None)
        }
    }

    /// Consumes characters until `predicate` returns false or EOF.
    /// Returns the span of consumed characters.
    fn consume_while(&mut self, predicate: impl Fn(u8) -> bool) -> io::Result<TokenSpan> {
        let start_offset = self.offset;
        let start_cursor = self.cursor;

        while let Some(b) = self.peek()? {
            if predicate(b) {
                self.consume()?;
            } else {
                break;
            }
        }
        Ok(TokenSpan::new(start_offset, self.offset))
    }

    /// Consumes a specific expected byte. Returns true if consumed, false if not found or EOF.
    fn consume_char(&mut self, expected: u8) -> io::Result<bool> {
        if let Some(c) = self.peek()? {
            if c == expected {
                self.consume()?;
                return Ok(true);
            }
        }
        Ok(false)
    }

    /// Tries to match a keyword. Returns `Some(TokenKind)` if matched, `None` otherwise.
    fn try_match_keyword(&self, slice: &[u8]) -> Option<TokenKind> {
        match slice {
            b"graph" => Some(TokenKind::Graph),
            b"flowchart" => Some(TokenKind::Flowchart),
            b"sequence" => Some(TokenKind::Sequence),
            b"class" => Some(TokenKind::Class),
            b"state" => Some(TokenKind::State),
            b"erDiagram" => Some(TokenKind::ErDiagram),
            b"gitGraph" => Some(TokenKind::GitGraph),
            b"gantt" => Some(TokenKind::Gantt),
            b"pie" => Some(TokenKind::Pie),
            b"c4diagram" => Some(TokenKind::C4Diagram),
            b"journey" => Some(TokenKind::Journey),
            b"requirement" => Some(TokenKind::Requirement),
            _ => None,
        }
    }

    /// Lexes the next token from the input stream.
    pub fn next_token(&mut self) -> Result<Token, LexerError> {
        loop {
            let start_offset = self.offset;
            let current_byte = match self.peek() {
                Ok(Some(b)) => b,
                Ok(None) if self.eof_reached => {
                    return Ok(Token::new(TokenKind::Eof, TokenSpan::new(start_offset, start_offset)))
                },
                Err(e) => return Err(LexerError {
                    src: miette::NamedSource::new("input", "".to_string()), // Placeholder, will be replaced by CLI
                    bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1),
                    help: Some(format!("I/O error: {}", e)),
                }),
                Ok(None) => continue, // Try filling buffer again if it was empty but not EOF
            };

            let token_kind: TokenKind;

            match current_byte {
                b' ' | b'\t' => {
                    let span = self.consume_while(|b| b == b' ' || b == b'\t').map_err(|e| LexerError {
                        src: miette::NamedSource::new("input", "".to_string()),
                        bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1),
                        help: Some(format!("I/O error during whitespace consumption: {}", e)),
                    })?;
                    // We can choose to return whitespace tokens or skip them.
                    // For a parser, skipping is often preferred unless whitespace is significant.
                    // For now, let's return them for full fidelity, but the parser will ignore.
                    token_kind = TokenKind::Whitespace;
                }
                b'\n' | b'\r' => {
                    let start_nl_offset = self.offset;
                    self.consume().map_err(|e| LexerError {
                        src: miette::NamedSource::new("input", "".to_string()),
                        bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1),
                        help: Some(format!("I/O error during newline consumption: {}", e)),
                    })?;
                    if current_byte == b'\r' && self.peek().map_err(|e| LexerError {
                        src: miette::NamedSource::new("input", "".to_string()),
                        bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1),
                        help: Some(format!("I/O error during newline peek: {}", e)),
                    })?.unwrap_or(0) == b'\n' {
                        self.consume().map_err(|e| LexerError {
                            src: miette::NamedSource::new("input", "".to_string()),
                            bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1),
                            help: Some(format!("I/O error during newline consumption: {}", e)),
                        })?; // Consume \n for CRLF
                    }
                    self.current_line += 1;
                    self.line_start_offsets.push(self.offset);
                    return Ok(Token::new(TokenKind::Newline, TokenSpan::new(start_nl_offset, self.offset)));
                }
                b'-' => {
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                            token_kind = TokenKind::ArrowRight; // -->
                        } else {
                            // This would be an invalid token like "--" without an arrow head.
                            // For now, let's treat it as an identifier or error.
                            // For strictness, if it's not a known arrow, it's an identifier or error.
                            // Here, we'll just fall through and let the identifier logic handle it if it matches.
                            // Or, for very strict, it's an error. Let's assume it's part of an identifier for now.
                            // A more robust lexer would have a fallback for partial matches.
                            // For Mermaid, "--" is typically not a token itself.
                            // We'll revert the consume and handle as Identifier or Invalid.
                            // This part needs careful design for strictness.
                            // For simplicity, let's assume valid arrows are always fully formed.
                            // If it's just `--`, it might be part of an identifier.
                            // For now, let's treat it as an invalid sequence if it's not an arrow.
                            // A better approach: push back bytes or scan ahead.
                            // For now, we'll simplify and say if we hit `-` and it's not a known arrow, it's an Identifier starting with `-`.
                            // This makes the lexer simpler but might require parser to handle complex identifiers.
                            // Let's re-evaluate: Mermaid arrows are distinct.
                            // `-->` `---` `-.->` `<--` `==>` etc.
                            // If we see `--` it's likely a part of an arrow.
                            // For `-->`, we already handled. What about `---`?
                            // Let's make this more robust.
                            let mut current_offset = start_offset + 1; // After consuming first '-'
                            let mut current_cursor = self.cursor;

                            // Re-peek to see what comes next
                            let next_byte = self.peek().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?.unwrap_or(0);

                            if next_byte == b'-' { // Found `---`
                                self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; // Consume second '-'
                                if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                                    token_kind = TokenKind::ArrowRight; // `--->`
                                } else {
                                    // Could be `---`, which is not a standard arrow in flowcharts.
                                    // Treat as invalid or part of identifier.
                                    // For now, let's assume any sequence of dashes not forming an arrow is an identifier.
                                    token_kind = TokenKind::Identifier; // Fallback to identifier for `---`
                                }
                            } else if next_byte == b'.' { // Found `-.`
                                self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; // Consume '.'
                                if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                                    if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                                        token_kind = TokenKind::ArrowRight; // `-.->`
                                    } else {
                                        token_kind = TokenKind::Identifier; // `-.--` or similar
                                    }
                                } else {
                                    token_kind = TokenKind::Identifier; // `-.`
                                }
                            } else {
                                // Just `-`, treat as identifier or error. For strictness, this is an error unless it's a valid identifier char.
                                token_kind = TokenKind::Identifier; // Simplified: treat as part of identifier
                            }
                        }
                    } else if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        token_kind = TokenKind::ArrowRight; // `->`
                    } else {
                        // Just `-`, part of identifier
                        token_kind = TokenKind::Identifier;
                    }
                }
                b'<' => { // Could be `<--` or `<->`
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                            token_kind = TokenKind::ArrowBoth; // `<->`
                        } else if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                            if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                                token_kind = TokenKind::ArrowLeft; // `<---`
                            } else {
                                token_kind = TokenKind::ArrowLeft; // `<--`
                            }
                        } else {
                            // `<` followed by `-` but not `->` or `--`
                            token_kind = TokenKind::Identifier; // Treat as part of identifier
                        }
                    } else {
                        // Just `<`, treat as identifier or error
                        token_kind = TokenKind::Identifier;
                    }
                }
                b'=' => { // Could be `==>`, `==`, `===`
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.consume_char(b'=').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        if self.consume_char(b'>').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                            token_kind = TokenKind::ArrowRight; // `==>`
                        } else {
                            // `==`, treat as part of identifier
                            token_kind = TokenKind::Identifier;
                        }
                    } else {
                        // `=`, treat as part of identifier
                        token_kind = TokenKind::Identifier;
                    }
                }
                b'x' => { // `x--x`
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?
                        && self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?
                        && self.consume_char(b'x').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        token_kind = TokenKind::ArrowX; // `x--x`
                    } else {
                        token_kind = TokenKind::Identifier; // Just `x` or `x-` etc.
                    }
                }
                b'o' => { // `o--o` or `o--`
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?
                        && self.consume_char(b'-').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        if self.consume_char(b'o').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                            token_kind = TokenKind::ArrowBoth; // `o--o`
                        } else {
                            token_kind = TokenKind::ArrowOpen; // `o--` (open arrow tail)
                        }
                    } else {
                        token_kind = TokenKind::Identifier; // Just `o` or `o-`
                    }
                }
                b':' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::Colon; }
                b';' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::Semicolon; }
                b',' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::Comma; }
                b'.' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::Dot; }
                b'(' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::ParenOpen; }
                b')' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::ParenClose; }
                b'[' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::BracketOpen; }
                b']' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::BracketClose; }
                b'{' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::CurlyOpen; }
                b'}' => { self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; token_kind = TokenKind::CurlyClose; }
                b'"' => { // String literal
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; // Consume opening quote
                    let string_start_offset = self.offset;
                    let mut escaped = false;
                    while let Some(b) = self.peek().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? {
                        if b == b'"' && !escaped {
                            break;
                        }
                        if b == b'\\' {
                            escaped = !escaped; // Toggle escaped state
                        } else {
                            escaped = false;
                        }
                        self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    }
                    let string_end_offset = self.offset;
                    if self.consume_char(b'"').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })? { // Consume closing quote
                        token_kind = TokenKind::StringLiteral;
                        return Ok(Token::new(TokenKind::StringLiteral, TokenSpan::new(string_start_offset, string_end_offset)));
                    } else {
                        // Unclosed string literal
                        return Err(LexerError {
                            src: miette::NamedSource::new("input", "".to_string()),
                            bad_char_span: miette::SourceSpan::from(start_offset..self.offset),
                            help: Some("Unclosed string literal. Expected '\"'.".to_string()),
                        });
                    }
                }
                b'%' => { // Comments: `%%` or `%% comment %%`
                    self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    if self.peek().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?.unwrap_or(0) == b'%' {
                        self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                        let comment_start_offset = self.offset;
                        self.consume_while(|b| b != b'\n' && b != b'\r').map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                        token_kind = TokenKind::Comment;
                        // For comments, we usually don't need the span to exclude `%%`, but rather the content.
                        // Let's make the span include `%%` for simplicity for now, or adjust `TokenKind::Comment` to hold content.
                        return Ok(Token::new(TokenKind::Comment, TokenSpan::new(comment_start_offset, self.offset)));
                    } else {
                        // Just a single '%', treat as invalid or part of identifier
                        return Err(LexerError {
                            src: miette::NamedSource::new("input", "".to_string()),
                            bad_char_span: miette::SourceSpan::from(start_offset..self.offset),
                            help: Some("Unexpected character '%'. Mermaid comments start with '%%'.".to_string()),
                        });
                    }
                }
                b'0'..=b'9' => { // Number literal
                    let span = self.consume_while(|b| b.is_ascii_digit()).map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;
                    token_kind = TokenKind::NumberLiteral;
                    return Ok(Token::new(token_kind, span));
                }
                _ => { // Identifier or Invalid character
                    // Try to consume a valid identifier character sequence
                    let span = self.consume_while(|b| {
                        b.is_ascii_alphanumeric() || b == b'_' || b == b'-' || b == b'.'
                    }).map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?;

                    if span.is_empty() {
                        // If no characters were consumed, it's an invalid character
                        self.consume().map_err(|e| LexerError { src: miette::NamedSource::new("input", "".to_string()), bad_char_span: miette::SourceSpan::from(start_offset..start_offset + 1), help: None })?; // Consume the bad char
                        return Err(LexerError {
                            src: miette::NamedSource::new("input", "".to_string()),
                            bad_char_span: miette::SourceSpan::from(start_offset..self.offset),
                            help: Some(format!("Unexpected character: '{}'", current_byte as char)),
                        });
                    }

                    // Resolve the span to a string to check for keywords
                    let current_input_slice = &self.buffer[start_cursor..self.cursor];
                    if let Some(kind) = self.try_match_keyword(current_input_slice) {
                        token_kind = kind;
                    } else {
                        token_kind = TokenKind::Identifier;
                    }
                }
            }
            return Ok(Token::new(token_kind, TokenSpan::new(start_offset, self.offset)));
        }
    }

    /// Helper to get the line and column from a byte offset.
    pub fn get_line_col(&self, offset: usize) -> (usize, usize) {
        let line_index = self.line_start_offsets.iter()
            .rposition(|&start_offset| start_offset <= offset)
            .unwrap_or(0);
        let line_start_offset = self.line_start_offsets[line_index];
        (line_index + 1, offset - line_start_offset + 1)
    }
}

Explanation of Lexer Changes:

  • Generics R: Read: The Lexer now takes any type that implements std::io::Read, making it flexible for files, stdin, or memory buffers.
  • BufReader: Wraps the R with BufReader for efficient chunked reading.
  • buffer: Vec<u8>: An internal buffer stores chunks of bytes read from BufReader.
  • cursor and offset: cursor tracks position within buffer, offset tracks total bytes from the start of the input stream.
  • fill_buffer: This critical method ensures buffer always has data if available. It reads from reader into buffer when cursor reaches the end.
  • peek and consume: These methods operate on the buffer and automatically call fill_buffer when needed. They return io::Result<Option<u8>> to handle I/O errors and EOF.
  • consume_while: A helper that consumes bytes as long as a predicate is true, returning the TokenSpan.
  • TokenSpan usage: Instead of token.value = "...", we now have token.span = TokenSpan::new(start_offset, self.offset). This is the zero-copy part.
  • Keyword Matching: Keywords are now matched against &[u8] slices from the buffer, avoiding String conversions until absolutely necessary.
  • Error Handling: I/O errors are propagated as LexerError that wraps io::Error. miette::NamedSource is a placeholder for now, as the actual source content is not stored in the lexer (it’s streamed). This will be handled by the CLI layer which holds the full source.
  • Arrow and Literal Handling: The logic for identifying complex arrows (-->, x--x, etc.) and string/number literals is updated to use peek and consume on bytes.

c) Testing This Component

To test the lexer, we can create a small test in src/lexer.rs that reads from a Cursor (which implements io::Read).

// src/lexer.rs (add this at the bottom, inside `#[cfg(test)] mod tests { ... }`)

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    fn get_lexer(input: &str) -> Lexer<Cursor<Vec<u8>>> {
        Lexer::new(Cursor::new(input.as_bytes().to_vec()))
    }

    #[test]
    fn test_lexer_empty_input() {
        let mut lexer = get_lexer("");
        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Eof);
        assert_eq!(token.span, TokenSpan::new(0, 0));
    }

    #[test]
    fn test_lexer_simple_flowchart() {
        let input = "graph TD\n    A-->B";
        let mut lexer = get_lexer(input);
        let source_str = input; // For resolving spans

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Graph);
        assert_eq!(token.span.resolve(source_str), "graph");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Whitespace);
        assert_eq!(token.span.resolve(source_str), " ");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Identifier);
        assert_eq!(token.span.resolve(source_str), "TD");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Newline);

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Whitespace);
        assert_eq!(token.span.resolve(source_str), "    ");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Identifier);
        assert_eq!(token.span.resolve(source_str), "A");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::ArrowRight);
        assert_eq!(token.span.resolve(source_str), "-->");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Identifier);
        assert_eq!(token.span.resolve(source_str), "B");

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Eof);
    }

    #[test]
    fn test_lexer_arrows() {
        let input = "A-->B\nC<--D\nE<->F\nG==>H\nI x--x J\nK o--o L\nM o-- N";
        let mut lexer = get_lexer(input);
        let source_str = input;

        // A-->B
        lexer.next_token().unwrap(); // A
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowRight);
        lexer.next_token().unwrap(); // B
        lexer.next_token().unwrap(); // Newline

        // C<--D
        lexer.next_token().unwrap(); // C
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowLeft);
        lexer.next_token().unwrap(); // D
        lexer.next_token().unwrap(); // Newline

        // E<->F
        lexer.next_token().unwrap(); // E
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowBoth);
        lexer.next_token().unwrap(); // F
        lexer.next_token().unwrap(); // Newline

        // G==>H
        lexer.next_token().unwrap(); // G
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowRight);
        lexer.next_token().unwrap(); // H
        lexer.next_token().unwrap(); // Newline

        // I x--x J
        lexer.next_token().unwrap(); // I
        lexer.next_token().unwrap(); // Whitespace
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowX);
        lexer.next_token().unwrap(); // Whitespace
        lexer.next_token().unwrap(); // J
        lexer.next_token().unwrap(); // Newline

        // K o--o L
        lexer.next_token().unwrap(); // K
        lexer.next_token().unwrap(); // Whitespace
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowBoth); // o--o
        lexer.next_token().unwrap(); // Whitespace
        lexer.next_token().unwrap(); // L
        lexer.next_token().unwrap(); // Newline

        // M o-- N
        lexer.next_token().unwrap(); // M
        lexer.next_token().unwrap(); // Whitespace
        assert_eq!(lexer.next_token().unwrap().kind, TokenKind::ArrowOpen); // o--
        lexer.next_token().unwrap(); // Whitespace
        lexer.next_token().unwrap(); // N
        lexer.next_token().unwrap(); // Eof
    }

    #[test]
    fn test_lexer_string_literal() {
        let input = "graph TD\nA[\"Hello World\"]";
        let mut lexer = get_lexer(input);
        let source_str = input;

        lexer.next_token().unwrap(); // graph
        lexer.next_token().unwrap(); // WS
        lexer.next_token().unwrap(); // TD
        lexer.next_token().unwrap(); // Newline
        lexer.next_token().unwrap(); // A
        lexer.next_token().unwrap(); // [

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::StringLiteral);
        assert_eq!(token.span.resolve(source_str), "Hello World");

        lexer.next_token().unwrap(); // ]
        lexer.next_token().unwrap(); // Eof
    }

    #[test]
    fn test_lexer_comment() {
        let input = "graph TD\n%% This is a comment\nA-->B";
        let mut lexer = get_lexer(input);
        let source_str = input;

        lexer.next_token().unwrap(); // graph
        lexer.next_token().unwrap(); // WS
        lexer.next_token().unwrap(); // TD
        lexer.next_token().unwrap(); // Newline

        let token = lexer.next_token().unwrap();
        assert_eq!(token.kind, TokenKind::Comment);
        assert_eq!(token.span.resolve(source_str), " This is a comment");

        lexer.next_token().unwrap(); // Newline
        lexer.next_token().unwrap(); // A
        lexer.next_token().unwrap(); // ArrowRight
        lexer.next_token().unwrap(); // B
        lexer.next_token().unwrap(); // Eof
    }

    #[test]
    fn test_lexer_unclosed_string() {
        let input = "graph TD\nA[\"Unclosed string]";
        let mut lexer = get_lexer(input);
        let _ = lexer.next_token().unwrap(); // graph
        let _ = lexer.next_token().unwrap(); // WS
        let _ = lexer.next_token().unwrap(); // TD
        let _ = lexer.next_token().unwrap(); // Newline
        let _ = lexer.next_token().unwrap(); // A
        let _ = lexer.next_token().unwrap(); // [
        let error = lexer.next_token();
        assert!(error.is_err());
        assert_eq!(error.unwrap_err().help.unwrap(), "Unclosed string literal. Expected '\"'.");
    }

    #[test]
    fn test_lexer_invalid_char() {
        let input = "graph TD\nA#B";
        let mut lexer = get_lexer(input);
        let _ = lexer.next_token().unwrap(); // graph
        let _ = lexer.next_token().unwrap(); // WS
        let _ = lexer.next_token().unwrap(); // TD
        let _ = lexer.next_token().unwrap(); // Newline
        let _ = lexer.next_token().unwrap(); // A
        let error = lexer.next_token();
        assert!(error.is_err());
        assert_eq!(error.unwrap_err().help.unwrap(), "Unexpected character: '#'");
    }
}

Debugging Tips:

  • Use dbg!(&token) to inspect tokens and their spans.
  • Step through the next_token method with a debugger to see how peek and consume interact with the buffer.
  • Ensure TokenSpan::resolve correctly extracts the string slice from your test input.

3. Core Implementation: Parser with Arena Allocation

Now we need to update our AST nodes and Parser to use bumpalo::Arena for allocation and Cow<'a, str> for strings where appropriate. This means our AST will be tied to a specific lifetime 'a, typically the lifetime of the input &str or the Arena itself.

a) Modify src/ast.rs - Lifetimes and Cow

We’ll introduce a lifetime parameter 'a to our AST structs and use Cow<'a, str> for string fields.

// src/ast.rs

use std::borrow::Cow;
use crate::lexer::TokenSpan; // Import TokenSpan

/// The top-level representation of a Mermaid diagram.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Diagram<'a> {
    pub diagram_type: DiagramType,
    pub statements: Vec<Statement<'a>>,
    pub span: TokenSpan,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum DiagramType {
    Flowchart,
    Sequence,
    Class,
    // ... other diagram types
}

/// Represents a single statement in the diagram (e.g., node definition, edge, subgraph).
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Statement<'a> {
    Node(Node<'a>),
    Edge(Edge<'a>),
    Subgraph(Subgraph<'a>),
    Direction(Direction),
    Comment(TokenSpan), // Comments are just spans
    // ... other statement types
}

/// Represents a node in a diagram.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Node<'a> {
    pub id: Cow<'a, str>, // Node ID, typically borrowed
    pub label: Option<Cow<'a, str>>, // Node label, can be borrowed or owned if fixed
    pub shape: NodeShape,
    pub span: TokenSpan,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum NodeShape {
    Rectangle,
    RoundedRectangle,
    // ... other shapes
    Default, // No explicit shape defined
}

/// Represents an edge between two nodes.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Edge<'a> {
    pub from: Cow<'a, str>, // Source node ID
    pub to: Cow<'a, str>,   // Target node ID
    pub label: Option<Cow<'a, str>>, // Edge label
    pub arrow_type: ArrowType,
    pub span: TokenSpan,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ArrowType {
    Normal,
    Open,
    Cross,
    // ... other arrow types
}

/// Represents a subgraph.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Subgraph<'a> {
    pub id: Cow<'a, str>,
    pub title: Option<Cow<'a, str>>,
    pub statements: Vec<Statement<'a>>,
    pub span: TokenSpan,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Direction {
    TD, TB, LR, RL, BT,
}

// ... Add other AST structs as needed, ensuring they also use lifetimes and Cow<'a, str>
// For example, if you have a `ClassMember` in a Class Diagram AST:
// pub struct ClassMember<'a> {
//     pub visibility: Option<Cow<'a, str>>,
//     pub member_type: Cow<'a, str>,
//     pub name: Cow<'a, str>,
//     pub span: TokenSpan,
// }

Explanation of AST Changes:

  • Lifetime Parameter 'a: All AST structs that contain borrowed data (slices from the input or arena) now have a lifetime parameter 'a. This ties the AST’s lifetime to the input source or the arena.
  • Cow<'a, str>: Instead of String, we use Cow<'a, str>.
    • Cow::Borrowed(&'a str): If the string data comes directly from the input buffer and doesn’t need modification, we can borrow it. This is zero-cost.
    • Cow::Owned(String): If the string needs to be modified (e.g., a rule fixes a label by adding quotes), we can convert it to Cow::Owned(String). This incurs a heap allocation, but only when strictly necessary.
  • TokenSpan: AST nodes now store TokenSpan for their overall position, allowing precise error reporting and source mapping.

b) Modify src/parser.rs - Parser struct and AST construction

The Parser will now take a bumpalo::Arena by mutable reference and use it to allocate AST nodes.

// src/parser.rs

use crate::ast::*; // Import all AST types
use crate::lexer::{Lexer, LexerError, Token, TokenKind, TokenSpan};
use std::borrow::Cow;
use std::collections::HashMap;
use miette::{Diagnostic, SourceSpan, NamedSource};
use thiserror::Error;
use bumpalo::Bump; // Import Bump (Arena)

/// Represents a parsing error.
#[derive(Debug, Clone, PartialEq, Eq, Diagnostic, Error)]
#[error("Parsing error")]
#[diagnostic(code(mermaid::parser::error))]
pub struct ParserError {
    #[source_code]
    pub src: NamedSource,
    #[label("Here")]
    pub bad_token_span: SourceSpan,
    pub expected: Option<String>,
    pub found: Option<String>,
    pub help: Option<String>,
}

/// The Parser for Mermaid diagrams.
/// It takes a lexer and an arena allocator to build the AST.
pub struct Parser<'a, R: std::io::Read> {
    lexer: Lexer<R>,
    current_token: Option<Token>,
    arena: &'a Bump, // Arena allocator for AST nodes
    source_content: &'a str, // Reference to the entire source content for span resolution
}

impl<'a, R: std::io::Read> Parser<'a, R> {
    /// Creates a new Parser instance.
    pub fn new(lexer: Lexer<R>, arena: &'a Bump, source_content: &'a str) -> Result<Self, LexerError> {
        let mut parser = Self {
            lexer,
            current_token: None,
            arena,
            source_content,
        };
        parser.advance()?; // Prime the parser with the first token
        Ok(parser)
    }

    /// Advances the lexer and updates the current token.
    fn advance(&mut self) -> Result<(), LexerError> {
        loop {
            let token = self.lexer.next_token()?;
            if token.kind == TokenKind::Whitespace {
                // Skip whitespace tokens, but keep them for span tracking if needed for formatting.
                // For parsing, we just ignore them.
                continue;
            }
            self.current_token = Some(token);
            break;
        }
        Ok(())
    }

    /// Peeks at the current token without consuming it.
    fn peek(&self) -> &Token {
        self.current_token.as_ref().expect("Parser's current_token should always be Some except at EOF or after an error")
    }

    /// Consumes the current token and returns it.
    fn consume(&mut self) -> Result<Token, ParserError> {
        let token = self.current_token.take().expect("Failed to consume token: current_token was None");
        self.advance().map_err(|e| self.lexer_error_to_parser_error(e))?;
        Ok(token)
    }

    /// Consumes the current token if its kind matches the expected kind.
    /// Returns the consumed token or a ParserError.
    fn expect(&mut self, expected_kind: TokenKind) -> Result<Token, ParserError> {
        let current_token = self.peek();
        if current_token.kind == expected_kind {
            self.consume()
        } else {
            let found_kind = current_token.kind.clone();
            let span = current_token.span;
            Err(ParserError {
                src: NamedSource::new("input", self.source_content.to_string()),
                bad_token_span: span.into(),
                expected: Some(format!("{:?}", expected_kind)),
                found: Some(format!("{:?}", found_kind)),
                help: Some(format!("Expected token {:?}, but found {:?}", expected_kind, found_kind)),
            })
        }
    }

    /// Helper to convert LexerError to ParserError, adding source content.
    fn lexer_error_to_parser_error(&self, lex_err: LexerError) -> ParserError {
        ParserError {
            src: NamedSource::new("input", self.source_content.to_string()),
            bad_token_span: lex_err.bad_char_span,
            expected: None,
            found: None,
            help: lex_err.help,
        }
    }

    /// Parses the entire Mermaid diagram.
    pub fn parse(&mut self) -> Result<Diagram<'a>, ParserError> {
        let start_span = self.peek().span;
        let diagram_type_token = self.expect_any_keyword()?; // e.g., 'graph', 'flowchart'
        let diagram_type = self.parse_diagram_type(&diagram_type_token)?;

        let mut statements = Vec::new();
        while self.peek().kind != TokenKind::Eof {
            // Handle newlines as statement separators, but don't add them to AST
            if self.peek().kind == TokenKind::Newline {
                self.consume()?;
                continue;
            }
            if self.peek().kind == TokenKind::Comment {
                let comment_token = self.consume()?;
                statements.push(Statement::Comment(comment_token.span));
                continue;
            }

            // Try to parse different statement types
            if let Ok(node) = self.parse_node_definition() {
                statements.push(Statement::Node(node));
            } else if let Ok(edge) = self.parse_edge() {
                statements.push(Statement::Edge(edge));
            } else if let Ok(subgraph) = self.parse_subgraph() {
                statements.push(Statement::Subgraph(subgraph));
            } else if let Ok(direction) = self.parse_direction() {
                statements.push(Statement::Direction(direction));
            } else {
                // If we can't parse anything, it's an unexpected token
                let bad_token = self.consume()?;
                return Err(ParserError {
                    src: NamedSource::new("input", self.source_content.to_string()),
                    bad_token_span: bad_token.span.into(),
                    expected: Some("node, edge, subgraph, or direction".to_string()),
                    found: Some(format!("{:?}", bad_token.kind)),
                    help: Some("Unexpected token in diagram body. Expected a statement.".to_string()),
                });
            }
        }
        let end_span = self.peek().span; // Eof token span
        let diagram_span = TokenSpan::new(start_span.start, end_span.end);

        Ok(Diagram {
            diagram_type,
            statements,
            span: diagram_span,
        })
    }

    /// Parses a diagram type keyword (e.g., 'graph', 'flowchart').
    fn expect_any_keyword(&mut self) -> Result<Token, ParserError> {
        let token = self.peek();
        match token.kind {
            TokenKind::Graph | TokenKind::Flowchart | TokenKind::Sequence |
            TokenKind::Class | TokenKind::State | TokenKind::ErDiagram |
            TokenKind::GitGraph | TokenKind::Gantt | TokenKind::Pie |
            TokenKind::C4Diagram | TokenKind::Journey | TokenKind::Requirement => {
                self.consume()
            },
            _ => Err(ParserError {
                src: NamedSource::new("input", self.source_content.to_string()),
                bad_token_span: token.span.into(),
                expected: Some("diagram type keyword (e.g., 'graph', 'flowchart')".to_string()),
                found: Some(format!("{:?}", token.kind)),
                help: Some("Mermaid diagram must start with a diagram type declaration.".to_string()),
            }),
        }
    }

    fn parse_diagram_type(&self, token: &Token) -> Result<DiagramType, ParserError> {
        match token.kind {
            TokenKind::Graph | TokenKind::Flowchart => Ok(DiagramType::Flowchart),
            TokenKind::Sequence => Ok(DiagramType::Sequence),
            TokenKind::Class => Ok(DiagramType::Class),
            // ... map other keywords to DiagramType
            _ => Err(ParserError {
                src: NamedSource::new("input", self.source_content.to_string()),
                bad_token_span: token.span.into(),
                expected: Some("valid diagram type keyword".to_string()),
                found: Some(format!("{:?}", token.kind)),
                help: Some("Unsupported or invalid diagram type.".to_string()),
            }),
        }
    }

    /// Parses a node definition (e.g., `A[Label]`).
    fn parse_node_definition(&mut self) -> Result<Node<'a>, ParserError> {
        let start_span = self.peek().span;
        let id_token = self.expect(TokenKind::Identifier)?;
        let id = Cow::Borrowed(id_token.span.resolve(self.source_content));

        let mut label: Option<Cow<'a, str>> = None;
        let mut shape = NodeShape::Default;

        if self.peek().kind == TokenKind::BracketOpen {
            self.consume()?; // Consume '['
            let label_token = self.expect(TokenKind::StringLiteral)
                .or_else(|_| self.expect(TokenKind::Identifier))?; // Labels can sometimes be unquoted identifiers
            label = Some(Cow::Borrowed(label_token.span.resolve(self.source_content)));
            self.expect(TokenKind::BracketClose)?; // Consume ']'
            shape = NodeShape::Rectangle; // Default shape for bracketed labels
        }
        // ... extend with other shapes like `((Label))` for rounded, `{Label}` for cylinder, etc.

        let end_span = if let Some(last_token) = &self.current_token {
            last_token.span
        } else {
            id_token.span // Fallback if no more tokens after ID
        };
        let node_span = TokenSpan::new(start_span.start, end_span.end);

        // Allocate Node on the arena
        Ok(Node {
            id,
            label,
            shape,
            span: node_span,
        })
    }

    /// Parses an edge definition (e.g., `A-->B`).
    fn parse_edge(&mut self) -> Result<Edge<'a>, ParserError> {
        let start_span = self.peek().span;
        let from_token = self.expect(TokenKind::Identifier)?;
        let from = Cow::Borrowed(from_token.span.resolve(self.source_content));

        let arrow_token = self.expect_any_arrow_type()?;
        let arrow_type = self.parse_arrow_type(&arrow_token)?;

        let to_token = self.expect(TokenKind::Identifier)?;
        let to = Cow::Borrowed(to_token.span.resolve(self.source_content));

        let edge_span = TokenSpan::new(start_span.start, to_token.span.end);

        // Allocate Edge on the arena
        Ok(Edge {
            from,
            to,
            label: None, // Add label parsing later if needed
            arrow_type,
            span: edge_span,
        })
    }

    fn expect_any_arrow_type(&mut self) -> Result<Token, ParserError> {
        let token = self.peek();
        match token.kind {
            TokenKind::ArrowRight | TokenKind::ArrowLeft | TokenKind::ArrowBoth |
            TokenKind::ArrowOpen | TokenKind::ArrowX => {
                self.consume()
            },
            _ => Err(ParserError {
                src: NamedSource::new("input", self.source_content.to_string()),
                bad_token_span: token.span.into(),
                expected: Some("an arrow type (e.g., '-->', '<--')".to_string()),
                found: Some(format!("{:?}", token.kind)),
                help: Some("Expected an arrow to connect nodes.".to_string()),
            }),
        }
    }

    fn parse_arrow_type(&self, token: &Token) -> Result<ArrowType, ParserError> {
        match token.kind {
            TokenKind::ArrowRight => Ok(ArrowType::Normal),
            TokenKind::ArrowLeft => Ok(ArrowType::Normal), // For now, treat both as normal, direction handled by from/to
            TokenKind::ArrowBoth => Ok(ArrowType::Normal), // Similarly
            TokenKind::ArrowOpen => Ok(ArrowType::Open),
            TokenKind::ArrowX => Ok(ArrowType::Cross),
            _ => unreachable!("Should only be called with arrow tokens"),
        }
    }

    /// Parses a subgraph definition. (Simplified for brevity)
    fn parse_subgraph(&mut self) -> Result<Subgraph<'a>, ParserError> {
        // This is a simplified placeholder. A real subgraph parsing would be recursive.
        let start_span = self.peek().span;
        self.expect(TokenKind::Subgraph)?; // Expect 'subgraph' keyword
        let id_token = self.expect(TokenKind::Identifier)?;
        let id = Cow::Borrowed(id_token.span.resolve(self.source_content));

        // Optional title
        let mut title: Option<Cow<'a, str>> = None;
        if self.peek().kind == TokenKind::StringLiteral {
            let title_token = self.consume()?;
            title = Some(Cow::Borrowed(title_token.span.resolve(self.source_content)));
        }

        self.expect(TokenKind::Newline)?; // Subgraph content starts on new line

        let mut statements = Vec::new();
        // Consume statements until 'end' or Eof
        while self.peek().kind != TokenKind::Eof && self.peek().kind != TokenKind::End {
            if self.peek().kind == TokenKind::Newline {
                self.consume()?;
                continue;
            }
            // Recursively parse inner statements (nodes, edges, nested subgraphs)
            if let Ok(node) = self.parse_node_definition() {
                statements.push(Statement::Node(node));
            } else if let Ok(edge) = self.parse_edge() {
                statements.push(Statement::Edge(edge));
            } else if let Ok(inner_subgraph) = self.parse_subgraph() { // Recursive call
                statements.push(Statement::Subgraph(inner_subgraph));
            } else if let Ok(direction) = self.parse_direction() {
                statements.push(Statement::Direction(direction));
            } else if self.peek().kind == TokenKind::Comment {
                let comment_token = self.consume()?;
                statements.push(Statement::Comment(comment_token.span));
            } else {
                // If we can't parse anything, break or error out.
                // For now, let's assume valid subgraph content or break on unknown.
                break;
            }
        }

        // Ensure 'end' keyword is present if not EOF
        let end_token = self.expect(TokenKind::End)?; // Expect 'end' keyword
        let subgraph_span = TokenSpan::new(start_span.start, end_token.span.end);

        Ok(Subgraph {
            id,
            title,
            statements,
            span: subgraph_span,
        })
    }

    /// Parses a direction statement (e.g., `TD`).
    fn parse_direction(&mut self) -> Result<Direction, ParserError> {
        let token = self.peek();
        match token.kind {
            TokenKind::Identifier => { // TD, LR, etc. are identifiers
                let id_str = token.span.resolve(self.source_content);
                let direction = match id_str {
                    "TD" | "TB" => Direction::TD,
                    "LR" => Direction::LR,
                    "RL" => Direction::RL,
                    "BT" => Direction::BT,
                    _ => return Err(ParserError {
                        src: NamedSource::new("input", self.source_content.to_string()),
                        bad_token_span: token.span.into(),
                        expected: Some("valid direction (TD, LR, etc.)".to_string()),
                        found: Some(id_str.to_string()),
                        help: Some("Invalid diagram direction.".to_string()),
                    }),
                };
                self.consume()?;
                Ok(direction)
            }
            _ => Err(ParserError {
                src: NamedSource::new("input", self.source_content.to_string()),
                bad_token_span: token.span.into(),
                expected: Some("direction identifier (TD, LR, etc.)".to_string()),
                found: Some(format!("{:?}", token.kind)),
                help: Some("Expected a diagram direction.".to_string()),
            }),
        }
    }
}

Explanation of Parser Changes:

  • Lifetime 'a and Bump: The Parser now holds a reference &'a Bump (the arena allocator) and a source_content: &'a str which is a reference to the entire input string. This source_content is crucial for TokenSpan::resolve.
  • Parser::new: Now takes the arena and source_content as arguments.
  • Cow::Borrowed: When creating Nodes, Edges, Subgraphs, the id, label, from, to, title fields are initialized with Cow::Borrowed(token.span.resolve(self.source_content)). This means the AST nodes directly reference parts of the original input string, avoiding new string allocations.
  • Error Handling: ParserError now includes source_content for better diagnostic reporting.
  • Allocation: The Node, Edge, Subgraph structs are allocated on the stack (temporarily) and then moved into the Vecs of statements. The Cow variants handle the borrowing of string data. The Vec itself will grow on the heap, but bumpalo would be used if we were allocating individual AST nodes directly on the arena using arena.alloc(Node { ... }). For now, Cow and TokenSpan are the primary zero-copy mechanisms. If the AST itself becomes very large and deep, we would refactor Vec<Statement<'a>> to &'a [Statement<'a>] and allocate the Statement slices on the arena. For typical Mermaid diagrams, Vec of Cows is often sufficient. Self-correction: For true arena allocation, the Diagram, Statement, Node, Edge, Subgraph structs themselves should be allocated on the arena. This means Vec would become &'a [Statement<'a>] or similar arena-backed collections. For this chapter, Cow is a good start for string data, and we’ll keep Vec for simplicity for now, as Vec allocations are typically efficient enough for collections of structured data, and the primary string data is Cow::Borrowed.

c) Testing This Component

Let’s add some basic parser tests. We’ll need to provide a Bump arena and the source content.

// src/parser.rs (add this at the bottom, inside `#[cfg(test)] mod tests { ... }`)

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use bumpalo::Bump;

    fn parse_test_input(input: &str) -> Result<Diagram, ParserError> {
        let arena = Bump::new();
        let lexer = Lexer::new(Cursor::new(input.as_bytes().to_vec()));
        let mut parser = Parser::new(lexer, &arena, input).unwrap();
        parser.parse()
    }

    #[test]
    fn test_parse_simple_flowchart() {
        let input = "graph TD\n    A-->B";
        let diagram = parse_test_input(input).unwrap();

        assert_eq!(diagram.diagram_type, DiagramType::Flowchart);
        assert_eq!(diagram.statements.len(), 2); // A-->B

        if let Statement::Direction(dir) = &diagram.statements[0] {
            assert_eq!(*dir, Direction::TD);
        } else {
            panic!("Expected Direction statement");
        }

        if let Statement::Edge(edge) = &diagram.statements[1] {
            assert_eq!(edge.from, Cow::Borrowed("A"));
            assert_eq!(edge.to, Cow::Borrowed("B"));
            assert_eq!(edge.arrow_type, ArrowType::Normal);
        } else {
            panic!("Expected Edge statement");
        }
    }

    #[test]
    fn test_parse_node_with_label() {
        let input = "flowchart LR\n    Node1[My Label]";
        let diagram = parse_test_input(input).unwrap();

        assert_eq!(diagram.diagram_type, DiagramType::Flowchart);
        assert_eq!(diagram.statements.len(), 2);

        if let Statement::Node(node) = &diagram.statements[1] {
            assert_eq!(node.id, Cow::Borrowed("Node1"));
            assert_eq!(node.label, Some(Cow::Borrowed("My Label")));
            assert_eq!(node.shape, NodeShape::Rectangle);
        } else {
            panic!("Expected Node statement");
        }
    }

    #[test]
    fn test_parse_subgraph() {
        let input = r#"graph TD
    subgraph My Subgraph
        A --> B
    end"#;
        let diagram = parse_test_input(input).unwrap();

        assert_eq!(diagram.diagram_type, DiagramType::Flowchart);
        assert_eq!(diagram.statements.len(), 2);

        if let Statement::Subgraph(subgraph) = &diagram.statements[1] {
            assert_eq!(subgraph.id, Cow::Borrowed("My")); // Simplified ID for now
            assert_eq!(subgraph.title, Some(Cow::Borrowed(" Subgraph"))); // Simplified title for now
            assert_eq!(subgraph.statements.len(), 1); // A --> B inside
            if let Statement::Edge(edge) = &subgraph.statements[0] {
                assert_eq!(edge.from, Cow::Borrowed("A"));
                assert_eq!(edge.to, Cow::Borrowed("B"));
            } else {
                panic!("Expected Edge inside subgraph");
            }
        } else {
            panic!("Expected Subgraph statement");
        }
    }

    #[test]
    fn test_parse_invalid_start() {
        let input = "A-->B"; // Missing graph/flowchart declaration
        let error = parse_test_input(input);
        assert!(error.is_err());
        let err = error.unwrap_err();
        assert_eq!(err.help.unwrap(), "Mermaid diagram must start with a diagram type declaration.".to_string());
    }
}

Debugging Tips:

  • Print the Diagram struct after parsing with dbg!(&diagram).
  • Carefully check the Cow::Borrowed values to ensure they correctly reference the input string.
  • If you encounter lifetime errors, double-check that all Cow and &'a str fields are consistently using the same lifetime parameter 'a and that the Bump arena is passed correctly.

4. Core Implementation: Benchmarking Setup

We’ll use criterion to measure the performance of our lexer and parser.

a) Create benches/parsing_benchmark.rs

// benches/parsing_benchmark.rs

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use std::io::Cursor;
use bumpalo::Bump;
use mermaid_tool::lexer::Lexer; // Assuming mermaid_tool is your crate name
use mermaid_tool::parser::Parser;
use std::fs;

// A small sample for quick checks
const SMALL_MERMAID: &str = r#"
graph TD
    A[Start] --> B(Process)
    B --> C{Decision?}
    C -- Yes --> D[End]
    C -- No --> E[Retry]
    E --> B
"#;

// A larger sample for more realistic benchmarks
const LARGE_MERMAID_PATH: &str = "benches/large_diagram.mmd";

fn lexer_benchmark(c: &mut Criterion) {
    let small_input = SMALL_MERMAID.to_string();
    let large_input = fs::read_to_string(LARGE_MERMAID_PATH)
        .expect("Failed to read large diagram file. Create one at benches/large_diagram.mmd");

    let mut group = c.benchmark_group("Lexer Performance");
    group.sample_size(100); // Increase sample size for more stable results

    group.bench_function("lexer_small_input", |b| {
        b.iter(|| {
            let cursor = Cursor::new(black_box(small_input.as_bytes().to_vec()));
            let mut lexer = Lexer::new(cursor);
            let mut tokens = Vec::new();
            while lexer.peek().unwrap().is_some() { // Check for EOF without consuming
                tokens.push(lexer.next_token().unwrap());
            }
            black_box(tokens);
        })
    });

    group.bench_function("lexer_large_input", |b| {
        b.iter(|| {
            let cursor = Cursor::new(black_box(large_input.as_bytes().to_vec()));
            let mut lexer = Lexer::new(cursor);
            let mut tokens = Vec::new();
            while lexer.peek().unwrap().is_some() {
                tokens.push(lexer.next_token().unwrap());
            }
            black_box(tokens);
        })
    });

    group.finish();
}

fn parser_benchmark(c: &mut Criterion) {
    let small_input = SMALL_MERMAID.to_string();
    let large_input = fs::read_to_string(LARGE_MERMAID_PATH)
        .expect("Failed to read large diagram file. Create one at benches/large_diagram.mmd");

    let mut group = c.benchmark_group("Parser Performance");
    group.sample_size(100);

    group.bench_function("parser_small_input", |b| {
        b.iter(|| {
            let arena = Bump::new(); // Allocate a new arena for each iteration
            let cursor = Cursor::new(black_box(small_input.as_bytes().to_vec()));
            let lexer = Lexer::new(cursor);
            let mut parser = Parser::new(lexer, &arena, &small_input).unwrap();
            black_box(parser.parse().unwrap());
        })
    });

    group.bench_function("parser_large_input", |b| {
        b.iter(|| {
            let arena = Bump::new();
            let cursor = Cursor::new(black_box(large_input.as_bytes().to_vec()));
            let lexer = Lexer::new(cursor);
            let mut parser = Parser::new(lexer, &arena, &large_input).unwrap();
            black_box(parser.parse().unwrap());
        })
    });

    group.finish();
}

criterion_group!(benches, lexer_benchmark, parser_benchmark);
criterion_main!(benches);

b) Create a large diagram file

Create benches/large_diagram.mmd with a substantial Mermaid diagram. You can generate one programmatically or paste a large example.

Example benches/large_diagram.mmd:

graph TD subgraph Section_1["Initialization"] A[Start] --> B(Setup Environment) B --> C{Config Loaded?} C -- Yes --> D[Load Resources] C -- No --> E[Log Error] E --> F(Stop) end subgraph Section_2["Main Processing Loop"] D --> G[Process Item 1] G --> H[Validate Item 1] H -- Valid --> I[Store Item 1] H -- Invalid --> J[Retry Item 1] J --> G I --> K[Process Item 2] K --> L[Validate Item 2] L -- Valid --> M[Store Item 2] L -- Invalid --> N[Retry Item 2] N --> K end subgraph Section_3["Cleanup"] M --> O(Generate Report) O --> P[Close Connections] P --> F end subgraph Section_4["Error Handling"] E --> Error_Handler[Centralized Error Handler] J --> Error_Handler N --> Error_Handler Error_Handler --> F end click A "https://example.com/start" "Start documentation" click B "https://example.com/setup" click I call handleItem1Click() linkStyle 0 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 2 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 3 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 4 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 5 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 6 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 7 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 8 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 9 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 10 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 11 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 12 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 13 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 14 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 15 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 16 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 17 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 18 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 19 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 20 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 21 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 22 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 23 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 24 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 25 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 26 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 27 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 28 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 29 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 30 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 31 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 32 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 33 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 34 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 35 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 36 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 37 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 38 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 39 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 40 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 41 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 42 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 43 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 44 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 45 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 46 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 47 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 48 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 49 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 50 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 51 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 52 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 53 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 54 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 55 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 56 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 57 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 58 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 59 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 60 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 61 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 62 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 63 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 64 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 65 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 66 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 67 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 68 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 69 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 70 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 71 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 72 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 73 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 74 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 75 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 76 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 77 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 78 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 79 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 80 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 81 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 82 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 83 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 84 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 85 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 86 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 87 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 88 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 89 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 90 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 91 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 92 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 93 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 94 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 95 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 96 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 97 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 98 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 99 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 100 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 101 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 102 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 103 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 104 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 105 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 106 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 107 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 108 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 109 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 110 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 111 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 112 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 113 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 114 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 115 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 116 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 117 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 118 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 119 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 120 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 121 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 122 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 123 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 124 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 125 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 126 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 127 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 128 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 129 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 130 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 131 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 132 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 133 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 134 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 135 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 136 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 137 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 138 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 139 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 140 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 141 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 142 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 143 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 144 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 145 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 146 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 147 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 148 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 149 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 150 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 151 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 152 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 153 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 154 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 155 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 156 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 157 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 158 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 159 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 160 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 161 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 162 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 163 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 164 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 165 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 166 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 167 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 168 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 169 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 170 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 171 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 172 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 173 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 174 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 175 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 176 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 177 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 178 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 179 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 180 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 181 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 182 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 183 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 184 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 185 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 186 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 187 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 188 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 189 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 190 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 191 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 192 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 193 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 194 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 195 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 196 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 197 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 198 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 199 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 200 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 201 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 202 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 203 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 204 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 205 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 206 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 207 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 208 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 209 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 210 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 211 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 212 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 213 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 214 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 215 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 216 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 217 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 218 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 219 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 220 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 221 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 222 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 223 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 224 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 225 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 226 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 227 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 228 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 229 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 230 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 231 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 232 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 233 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 234 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 235 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 236 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 237 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 238 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 239 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 240 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 241 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 242 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 243 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 244 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 245 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 246 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 247 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 248 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 249 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 250 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 251 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 252 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 253 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 254 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 255 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 256 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 257 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 258 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 259 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 260 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 261 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 262 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 263 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 264 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 265 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 266 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 267 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 268 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 269 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 270 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 271 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 272 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 273 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 274 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 275 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 276 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 277 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 278 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 279 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 280 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 281 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 282 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 283 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 284 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 285 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 286 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 287 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 288 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 289 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 290 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 291 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 292 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 293 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 294 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 295 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 296 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 297 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 298 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 299 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 300 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 301 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 302 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 303 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 304 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 305 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 306 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 307 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 308 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 309 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 310 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 311 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 312 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 313 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 314 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 315 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 316 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 317 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 318 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 319 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 320 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 321 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 322 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 323 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 324 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 325 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 326 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 327 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 328 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 329 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 330 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 331 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 332 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 333 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 334 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 335 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 336 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 337 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 338 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 339 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 340 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 341 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 342 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 343 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 344 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 345 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 346 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 347 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 348 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 349 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 350 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 351 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 352 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 353 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 354 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 355 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 356 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 357 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 358 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 359 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 360 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 361 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 362 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 363 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 364 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 365 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 366 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 367 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 368 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 369 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 370 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 371 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 372 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 373 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 374 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 375 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 376 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 377 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 378 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 379 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 380 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 381 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 382 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 383 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 384 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 385 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 386 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 387 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 388 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 389 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 390 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 391 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 392 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 393 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 394 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 395 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 396 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 397 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 398 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 399 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 400 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 401 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 402 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 403 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 404 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 405 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 406 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 407 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 408 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 409 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 410 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 411 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 412 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 413 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 414 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 415 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 416 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 417 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 418 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 419 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 420 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 421 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 422 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 423 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 424 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 425 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 426 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 427 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 428 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 429 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 430 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 431 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 432 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 433 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 434 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 435 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 436 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 437 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 438 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 439 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 440 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 441 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 442 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 443 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 444 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 445 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 446 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 447 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 448 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 449 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 450 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 451 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 452 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 453 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 454 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 455 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 456 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 457 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 458 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 459 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 460 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 461 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 462 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 463 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 464 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 465 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 466 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 467 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 468 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 469 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 470 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 471 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 472 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 473 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 474 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 475 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 476 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 477 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 478 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 479 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 480 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 481 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 482 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 483 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 484 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 485 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 486 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 487 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 488 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 489 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 490 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 491 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 492 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 493 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 494 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 495 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 496 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 497 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 498 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 499 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 500 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 501 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 502 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 503 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 504 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 505 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 506 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 507 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 508 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 509 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 510 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 511 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 512 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 513 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 514 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 515 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 516 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 517 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 518 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 519 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 520 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 521 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 522 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 523 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 524 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 525 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 526 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 527 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 528 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 529 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 530 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 531 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 532 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 533 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 534 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 535 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 536 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 537 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 538 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 539 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 540 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 541 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 542 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 543 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 544 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 545 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 546 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 547 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 548 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 549 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 550 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 551 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 552 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 553 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 554 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 555 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 556 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 557 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 558 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 559 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 560 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 561 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 562 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 563 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 564 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 565 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 566 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 567 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 568 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 569 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 570 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 571 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 572 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 573 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 574 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 575 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 576 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 577 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 578 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 579 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 580 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 581 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 582 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 583 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 584 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 585 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 586 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 587 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 588 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 589 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 590 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 591 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 592 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 593 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 594 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 595 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 596 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 597 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 598 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 599 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 600 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 601 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 602 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 603 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 604 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 605 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 606 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 607 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 608 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 609 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 610 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 611 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 612 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 613 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 614 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 615 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 616 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 617 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 618 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 619 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 620 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 621 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 622 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 623 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 624 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 625 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 626 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 627 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 628 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 629 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 630 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 631 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 632 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 633 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 634 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 635 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 636 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 637 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 638 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 639 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 640 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 641 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 642 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 643 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 644 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 645 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 646 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 647 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 648 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 649 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 650 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 651 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 652 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 653 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 654 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 655 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 656 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 657 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 658 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 659 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 660 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 661 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 662 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 663 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 664 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 665 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 666 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 667 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 668 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 669 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 670 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 671 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 672 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 673 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 674 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 675 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 676 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 677 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 678 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 679 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 680 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 681 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 682 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 683 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 684 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 685 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 686 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 687 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 688 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 689 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 690 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 691 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 692 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 693 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 694 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 695 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 696 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 697 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 698 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 699 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 700 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 701 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 702 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 703 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 704 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 705 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 706 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 707 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 708 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 709 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 710 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 711 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 712 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 713 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 714 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 715 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 716 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 717 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 718 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 719 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 720 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 721 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 722 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 723 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 724 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 725 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 726 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 727 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 728 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 729 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 730 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 731 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 732 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 733 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 734 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 735 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 736 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 737 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 738 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 739 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 740 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 741 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 742 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 743 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 744 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 745 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 746 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 747 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 748 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 749 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 750 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 751 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 752 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 753 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 754 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 755 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 756 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 757 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 758 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 759 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 760 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 761 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 762 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 763 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 764 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 765 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 766 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 767 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 768 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 769 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 770 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 771 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 772 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 773 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 774 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 775 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 776 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 777 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 778 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 779 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 780 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 781 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 782 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 783 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 784 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 785 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 786 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 787 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 788 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 789 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 790 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 791 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 792 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 793 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 794 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 795 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 796 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 797 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 798 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 799 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 800 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 801 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 802 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 803 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 804 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 805 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 806 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 807 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 808 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 809 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 810 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 811 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 812 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 813 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 814 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 815 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 816 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 817 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 818 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 819 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 820 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 821 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 822 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 823 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 824 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 825 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 826 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 827 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 828 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 829 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 830 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 831 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 832 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 833 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 834 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 835 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 836 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 837 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 838 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 839 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 840 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 841 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 842 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 843 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 844 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 845 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 846 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 847 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 848 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 849 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 850 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 851 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 852 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 853 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 854 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 855 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 856 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 857 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 858 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 859 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 860 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 861 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 862 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 863 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 864 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 865 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 866 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 867 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 868 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 869 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 870 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 871 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 872 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 873 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 874 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 875 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 876 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 877 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 878 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 879 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 880 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 881 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 882 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 883 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 884 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 885 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 886 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 887 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 888 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 889 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 890 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 891 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 892 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 893 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 894 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 895 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 896 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 897 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 898 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 899 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 900 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 901 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 902 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 903 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 904 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 905 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 906 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 907 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 908 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 909 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 910 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 911 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 912 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 913 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 914 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 915 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 916 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 917 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 918 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 919 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 920 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 921 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 922 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 923 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 924 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 925 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 926 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 927 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 928 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 929 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 930 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 931 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 932 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 933 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 934 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 935 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 936 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 937 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 938 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 939 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 940 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 941 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 942 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 943 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 944 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 945 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 946 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 947 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 948 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 949 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 950 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 951 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 952 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 953 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 954 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 955 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 956 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 957 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 958 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 959 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 960 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 961 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 962 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 963 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 964 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 965 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 966 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 967 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 968 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 969 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 970 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 971 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 972 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 973 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 974 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 975 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 976 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 977 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 978 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 979 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 980 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 981 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 982 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 983 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 984 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 985 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 986 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 987 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 988 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 989 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 990 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 991 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 992 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 993 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 994 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 995 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 996 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 997 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 998 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 999 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1000 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1001 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1002 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1003 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1004 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1005 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1006 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1007 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1008 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1009 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1010 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1011 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1012 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1013 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1014 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1015 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1016 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1017 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1018 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 1019 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 120 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 121 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 122 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 123 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 124 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 125 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 126 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 127 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 128 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 129 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 130 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 131 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 132 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 133 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 134 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 135 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 136 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 137 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 138 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 139 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 140 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 141 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 142 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 143 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 144 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 145 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 146 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 147 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 148 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 149 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 150 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 151 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 152 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 153 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 154 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 155 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 156 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 157 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 158 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 159 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 160 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 161 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 162 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 163 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 164 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 165 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 166 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 167 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 168 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 169 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 170 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 171 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 172 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 173 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 174 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 175 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 176 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 177 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 178 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 179 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 180 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 181 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 182 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 183 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 184 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 185 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 186 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 187 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 188 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 189 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 190 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 191 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 192 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 193 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 194 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 195 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 196 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 197 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 198 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 199 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 200 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 201 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 202 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 203 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 204 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 205 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 206 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 207 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 208 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 209 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 210 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 211 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 212 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 213 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 214 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 215 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 216 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 217 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 218 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 219 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 220 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 221 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 222 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 223 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 224 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 225 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 226 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 227 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 228 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 229 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 230 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 231 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 232 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 233 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 234 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 235 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 236 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 237 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 238 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 239 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 240 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 241 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 242 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 243 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 244 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 245 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 246 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 247 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 248 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 249 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 250 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 251 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 252 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 253 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 254 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 255 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 256 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 257 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 258 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 259 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 260 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 261 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 262 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 263 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 264 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 265 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 266 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 267 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 268 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 269 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 270 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 271 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 272 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 273 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 274 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 275 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 276 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 277 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 278 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 279 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 280 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 281 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 282 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 283 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 284 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 285 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 286 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 287 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 288 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 289 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 290 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 291 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 292 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 293 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 294 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 295 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 296 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 297 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 298 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 299 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 300 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 301 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 302 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 303 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 304 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 305 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 306 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 307 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 308 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 309 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 310 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 311 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 312 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 313 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 314 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 315 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 316 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 317 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 318 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 319 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 320 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 321 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 322 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 323 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 324 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 325 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 326 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 327 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 328 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 329 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 330 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 331 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 332 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 333 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 334 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 335 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 336 stroke:#333,stroke-width:2px,fill:none,stroke-dasharray: 5 5; linkStyle 337 stroke:#333,stroke-width:2px,fill