From b642f672f00986106dfde4dbfa3fc7851c9a9622 Mon Sep 17 00:00:00 2001 From: Katie McCormick Date: Fri, 17 Jan 2014 13:06:12 -0800 Subject: Doc change: Update CCS doc with new quota info. Fix for: b/12665669 Change-Id: I08f812d37ab6f4347f6401b3a9682c45d96adb81 --- docs/html/google/gcm/ccs.jd | 152 +-- docs/html/images/gcm/CCS-ack.png | Bin 55599 -> 54832 bytes docs/image_sources/gcm/CCS-ack.graffle | 1580 ++++++++++++++++++++++++++++++++ 3 files changed, 1677 insertions(+), 55 deletions(-) create mode 100644 docs/image_sources/gcm/CCS-ack.graffle diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd index d2177ca8a897..03addfdb6f60 100644 --- a/docs/html/google/gcm/ccs.jd +++ b/docs/html/google/gcm/ccs.jd @@ -8,7 +8,7 @@ page.title=GCM Cloud Connection Server (XMPP)

In this document

    -
  1. How to Use CCS +
  2. Establishing a Connection
    1. Authentication
    @@ -46,19 +46,20 @@ target="_android">CCS and User Notifications Signup Form
  3. Note: To try out this feature, sign up using this form.

    -

    The GCM Cloud Connection Server (CCS) is a connection server based on XMPP. -CCS allows 3rd-party app servers (which you're -responsible for implementing) to communicate -with Android devices by establishing a persistent TCP connection with Google -servers using the XMPP protocol. This communication is asynchronous and bidirectional.

    +

    The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a +persistent, asynchronous, bidirectional connection to Google servers. The +connection can be used to send and receive messages between your server and +your users' GCM-connected devices.

    +

    You can continue to use the HTTP request mechanism to send messages to GCM servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:

    + @@ -73,22 +74,34 @@ APIs. For examples, see Implementing GCM Server for a list of all the message parameters and which connection server(s) supports them.

    +

    Establishing a Connection

    -

    How to Use CCS

    +

    CCS just uses XMPP as an authenticated transport layer, so you can use most +XMPP libraries to manage the connection. For an example, see +Java sample using the Smack library.

    -

    GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on -{@code http://gcm.googleapis.com} port 5235.

    +

    The CCS XMPP endpoint runs at {@code gcm.googleapis.com:5235}. When testing +functionality (with non-production users), you should instead connect to +{@code gcm-staging.googleapis.com:5236} (note the different port). Testing on +staging (a smaller environment where the latest CCS builds run) is beneficial +both for isolating real users from test code, as well as for early detection of +unexpected behavior changes.

    -

    CCS requires a Transport Layer Security (TLS) connection. That means the XMPP -client must initiate a TLS connection. -For example in Java, you would call {@code setSocketFactory(SSLSocketFactory)}.

    +

    The connection has two important requirements:

    -

    CCS requires a SASL PLAIN authentication mechanism using -{@code <your_GCM_Sender_Id>@gcm.googleapis.com} (GCM sender ID) and the -API key as the password, where the sender ID and API key are the same as described -in Getting Started.

    + -

    You can use most XMPP libraries to interact with CCS.

    +

    If at any point the connection fails, you should immediately reconnect. +There is no need to back off after a disconnect that happens after +authentication.

    Authentication

    @@ -100,11 +113,11 @@ in Getting Started.

    Server

    <str:features xmlns:str="http://etherx.jabber.org/streams">
    - <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    -   <mechanism>X-OAUTH2</mechanism>
    -   <mechanism>X-GOOGLE-TOKEN</mechanism>
    -   <mechanism>PLAIN</mechanism>
    - </mechanisms>
    + <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    +   <mechanism>X-OAUTH2</mechanism>
    +   <mechanism>X-GOOGLE-TOKEN</mechanism>
    +   <mechanism>PLAIN</mechanism>
    + </mechanisms>
     </str:features>
     
    @@ -118,16 +131,18 @@ mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>
    <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

    Message Format

    -

    CCS uses normal XMPP <message> stanzas. The body of the message must be: -

    +

    Once the XMPP connection is established, CCS and your server use normal XMPP +<message> stanzas to send JSON-encoded messages back and +forth. The body of the <message> must be:

     <gcm xmlns:google:mobile:data>
         JSON payload
     </gcm>
     
    -

    The JSON payload for server-to-device is similar to what the GCM http endpoint -uses, with these exceptions:

    +

    The JSON payload for regular GCM messages is similar to +what the GCM http endpoint uses, with these +exceptions:

    -
  4. For ACK/NACK messages that are special control messages, you also need to -include a {@code message_type} field in the JSON message. The value can be either -'ack' or 'nack'. For example: +

    In addition to regular GCM messages, control messages are sent, indicated by +the {@code message_type} field in the JSON object. The value can be either +'ack' or 'nack', or 'control' (see formats below). Any GCM message with an +unknown {@code message_type} can be ignored by your server.

    -
    message_type = ('ack');
    -
  5. -

    For each device message your app server receives from CCS, it needs to send an ACK message. It never needs to send a NACK message. If you don't send an ACK for a message, @@ -251,7 +265,9 @@ message is "nack". A NACK message contains:

    </message> -

    The following table lists some of the more common NACK error codes.

    +

    The following table lists NACK error codes. Unless otherwise +indicated, a NACKed message should not be retried. Unexpected NACK error codes +should be treated the same as {@code INTERNAL_SERVER_ERROR}.

    Table 1. NACK error codes.

    @@ -262,8 +278,17 @@ message is "nack". A NACK message contains:

    Description +{@code BAD_ACK} +The ACK message is improperly formed. + + {@code BAD_REGISTRATION} -The device has a registration ID, but it's invalid. +The device has a registration ID, but it's invalid or expired. + + +{@code CONNECTION_DRAINING} +The message couldn't be processed because the connection is draining. The +message should be immediately retried over another connection. {@code DEVICE_UNREGISTERED} @@ -274,25 +299,20 @@ message is "nack". A NACK message contains:

    The server encountered an error while trying to process the request. -{@code SERVICE_UNAVAILABLE} -The CCS connection server is temporarily unavailable, try again later -(using exponential backoff, etc.). +{@code INVALID_JSON} +The JSON message payload was not valid. -{@code BAD_ACK} -The ACK message is improperly formed. - - -{@code AUTHENTICATION_FAILED} -This is a 401 error indicating that there was an error authenticating the sender account. - - -{@code INVALID_TTL} -There was an error in the supplied "time to live" value. +{@code QUOTA_EXCEEDED} +The rate of messages to a particular registration ID (in other words, to a +sender/device pair) is too high. If you want to retry the message, try using a slower +rate. -{@code JSON_TYPE_ERROR} -There was an error in the supplied JSON data type. +{@code SERVICE_UNAVAILABLE} +CCS is not currently able to process the message. The +message should be retried over the same connection using exponential backoff +with an initial delay of 1 second. @@ -319,6 +339,28 @@ A stanza error contains:

    </message> +

    Control messages

    + +

    Periodically, CCS needs to close down a connection to perform load balancing. Before it +closes the connection, CCS sends a {@code CONNECTION_DRAINING} message to indicate that the connection is being drained +and will be closed soon. "Draining" refers to shutting off the flow of messages coming into a +connection, but allowing whatever is already in the pipeline to continue. When you receive +a {@code CONNECTION_DRAINING} message, you should immediately begin sending messages to another CCS +connection, opening a new connection if necessary. You should, however, keep the original +connection open and continue receiving messages that may come over the connection (and +ACKing them)—CCS will handle initiating a connection close when it is ready.

    + +

    The {@code CONNECTION_DRAINING} message looks like this:

    +
    <message>
    +  <data:gcm xmlns:data="google:mobile:data">
    +  {
    +    "message_type":"control"
    +    "control_type":"CONNECTION_DRAINING"
    +  }
    +  </data:gcm>
    +</message>
    + +

    {@code CONNECTION_DRAINING} is currently the only {@code control_type} supported.

    Upstream Messages

    @@ -381,7 +423,7 @@ response to the above message:

    Every message sent to CCS receives either an ACK or a NACK response. Messages that haven't received one of these responses are considered pending. If the pending -message count reaches 1000, the 3rd-party app server should stop sending new messages +message count reaches 100, the 3rd-party app server should stop sending new messages and wait for CCS to acknowledge some of the existing pending messages as illustrated in figure 1:

    @@ -395,7 +437,7 @@ figure 1:

    if there are too many unacknowledged messages. Therefore, the 3rd-party app server should "ACK" upstream messages, received from the client application via CCS, as soon as possible to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't -apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party app server +apply to these ACKs. Even if the pending message count reaches 100, the 3rd-party app server should continue sending ACKs for messages received from CCS to avoid blocking delivery of new upstream messages.

    @@ -795,7 +837,7 @@ USERNAME = "Your GCM Sender Id" PASSWORD = "API Key" REGISTRATION_ID = "Registration Id of the target device" -unacked_messages_quota = 1000 +unacked_messages_quota = 100 send_queue = [] # Return a random alphanumerical id diff --git a/docs/html/images/gcm/CCS-ack.png b/docs/html/images/gcm/CCS-ack.png index bce2ab2f5a1d..4633157a7067 100644 Binary files a/docs/html/images/gcm/CCS-ack.png and b/docs/html/images/gcm/CCS-ack.png differ diff --git a/docs/image_sources/gcm/CCS-ack.graffle b/docs/image_sources/gcm/CCS-ack.graffle new file mode 100644 index 000000000000..addd456861fa --- /dev/null +++ b/docs/image_sources/gcm/CCS-ack.graffle @@ -0,0 +1,1580 @@ + + + + + ActiveLayerIndex + 0 + ApplicationVersion + + com.omnigroup.OmniGrafflePro + 139.18.0.187838 + + AutoAdjust + + BackgroundGraphic + + Bounds + {{0, 0}, {576.00002479553223, 733}} + Class + SolidGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 2 + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + + + + BaseZoom + 0 + CanvasOrigin + {0, 0} + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2013-08-08 01:54:22 +0000 + Creator + Katie McCormick + DisplayScale + 1 0/72 in = 1.0000 in + GraphDocumentVersion + 8 + GraphicsList + + + Bounds + {{89, 329}, {169, 44}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 250 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 Now app server can send\ +message no. 101} + + Wrap + NO + + + Bounds + {{102, 266}, {114, 44}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 249 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 App server waits\ +for ack 1} + + Wrap + NO + + + Bounds + {{153, 154}, {98, 44}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 244 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 Average\ +response time} + + Wrap + NO + + + Class + LineGraphic + Head + + ID + 226 + Position + 0.375 + + ID + 242 + Points + + {263.00000095367432, 314.5} + {261, 99} + + Style + + stroke + + Color + + b + 0.112257 + g + 0.107007 + r + 0.934433 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 227 + Position + 0.34722220897674561 + + + + Class + LineGraphic + Head + + ID + 227 + Position + 0.3541666567325592 + + ID + 241 + Points + + {261, 99} + {262.50000071525574, 314.5} + + Style + + stroke + + Color + + b + 0.112257 + g + 0.107007 + r + 0.934433 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 226 + Position + 0.375 + + + + Class + LineGraphic + Head + + ID + 227 + + ID + 240 + Points + + {257.5, 336.5} + {288, 314.5} + + Style + + stroke + + Color + + b + 0.112257 + g + 0.107007 + r + 0.934433 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 239 + Points + + {231, 288.50000116229057} + {231, 251.25} + + Style + + stroke + + Color + + b + 0.112257 + g + 0.107007 + r + 0.934433 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 238 + Position + 0.56800001859664917 + + + + Class + LineGraphic + ID + 238 + Points + + {231, 253} + {231, 315.5} + + Style + + stroke + + Color + + b + 0.112257 + g + 0.107007 + r + 0.934433 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Bounds + {{476, 33}, {49, 32}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 18 + + ID + 230 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs36 \cf0 CCS} + + Wrap + NO + + + Bounds + {{243, 35}, {101, 32}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 18 + + ID + 229 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs36 \cf0 App Server} + + Wrap + NO + + + Class + LineGraphic + ID + 228 + Points + + {288, 252} + {216, 252} + + Style + + stroke + + HeadArrow + 0 + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 227 + Points + + {288, 314.5} + {216, 314.5} + + Style + + stroke + + HeadArrow + 0 + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 226 + Points + + {288, 99} + {216, 99} + + Style + + stroke + + HeadArrow + 0 + Legacy + + TailArrow + 0 + + + + + Bounds + {{393.69128000000001, 348.37441999999999}, {57, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 223 + Rotation + 23 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 no. 101} + + Wrap + NO + + + Bounds + {{290.12054000000001, 420.17102}, {60, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 14 + + ID + 222 + Rotation + 341 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 ack 100} + + Wrap + NO + + + Class + LineGraphic + ID + 220 + Points + + {504, 351} + {288, 463} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Bounds + {{430.51697000000001, 279.19488999999999}, {44, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 14 + + ID + 219 + Rotation + 341 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 ack.. } + + Wrap + NO + + + Bounds + {{390.63733000000002, 258.42700000000002}, {44, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 14 + + ID + 218 + Rotation + 341 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 ack 2} + + Wrap + NO + + + Bounds + {{290.74178999999998, 239.21059}, {57, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 217 + Rotation + 23 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 no. 100} + + Wrap + NO + + + Bounds + {{342.63623000000001, 185.82861}, {38, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 216 + Rotation + 18 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 no...} + + Wrap + NO + + + Bounds + {{361.60431, 234}, {44, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Font + Helvetica + Size + 14 + + ID + 209 + Rotation + 341 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 ack 1} + + Wrap + NO + + + Bounds + {{351.16005999999999, 153.43960999999999}, {42, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 172 + Rotation + 18 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 no. 2} + + Wrap + NO + + + Bounds + {{363, 117}, {42, 27}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + ID + 171 + Rotation + 18 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs28 \cf0 no. 1} + + Wrap + NO + + + Class + LineGraphic + ID + 169 + Points + + {504, 200.62189000000001} + {288, 312.62189000000001} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 168 + Points + + {504, 241.00763000000001} + {288, 353.00763000000001} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 167 + Points + + {504, 279} + {288, 391} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 165 + Points + + {289, 391} + {505, 492} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 164 + Points + + {288, 353} + {504, 454} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 163 + Points + + {288, 313} + {504, 414} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 162 + Points + + {288, 180} + {504, 281} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 161 + Points + + {288, 252} + {504, 353} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 160 + Points + + {288, 139.5} + {504, 240.5} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + Head + + ID + 158 + Position + 0.29398149251937866 + + ID + 159 + Points + + {288, 98.000000596046448} + {504, 199.00000476837158} + + Style + + stroke + + Color + + b + 0.934433 + g + 0 + r + 0.122713 + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 157 + Position + 0.060185186564922333 + + + + Class + LineGraphic + ID + 158 + Points + + {504, 72} + {504, 504} + + Style + + stroke + + HeadArrow + 0 + Legacy + + TailArrow + 0 + + + + + Class + LineGraphic + ID + 157 + Points + + {288, 72} + {288, 504} + + Style + + stroke + + HeadArrow + 0 + Legacy + + TailArrow + 0 + + + + + GridInfo + + ShowsGrid + YES + + GuidesLocked + NO + GuidesVisible + YES + HPages + 1 + ImageCounter + 1 + KeepToScale + + Layers + + + Lock + NO + Name + Layer 1 + Print + YES + View + YES + + + LayoutInfo + + Animate + NO + circoMinDist + 18 + circoSeparation + 0.0 + layoutEngine + dot + neatoSeparation + 0.0 + twopiSeparation + 0.0 + + LinksVisible + NO + MagnetsVisible + NO + MasterSheets + + ModificationDate + 2014-01-22 22:42:38 +0000 + Modifier + Katie McCormick + NotesVisible + NO + Orientation + 2 + OriginVisible + NO + PageBreaks + YES + PrintInfo + + NSBottomMargin + + float + 41 + + NSHorizonalPagination + + int + 0 + + NSLeftMargin + + float + 18 + + NSPaperSize + + size + {612.00002479553223, 792} + + NSPrintReverseOrientation + + int + 0 + + NSRightMargin + + float + 18 + + NSTopMargin + + float + 18 + + + PrintOnePage + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Canvas 1 + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + YES + UniqueID + 1 + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + ExpandedCanvases + + + name + Canvas 1 + + + Frame + {{170, 139}, {1218, 882}} + ListView + + OutlineWidth + 142 + RightSidebar + + ShowRuler + + Sidebar + + SidebarWidth + 120 + VisibleRegion + {{40.5, 0}, {534.5, 364}} + Zoom + 2 + ZoomValues + + + Canvas 1 + 2 + 1 + + + + + -- cgit v1.2.3-59-g8ed1b