├── package.json ├── examples ├── 2_deep.json ├── dialogue_tree.json ├── jackets.json ├── simple.json └── dialogue_tree.graffle ├── README.markdown ├── script └── graffle2json.rb ├── test └── convo-test.js └── lib └── convo.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "convo", 3 | "version": "0.0.1", 4 | "author": "Patrick Ewing ", 5 | "description": "A tiny conversation tree runner", 6 | "dependencies" : { 7 | "colors" : "*", 8 | "underscore" : "*", 9 | "prompt" : "0.1.12" 10 | }, 11 | "devDependencies": { 12 | "vows": "0.6.0", 13 | "gently": "*", 14 | "winston": "*" 15 | }, 16 | "license": "MIT", 17 | "engine": { 18 | "node": ">=6.5" 19 | } 20 | } -------------------------------------------------------------------------------- /examples/2_deep.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Did you know Jackalope milk has large number of purported health benefits, and fetches high prices across the American southwest?", 3 | "children": [ 4 | { 5 | "name": "Yes", 6 | "children": [ 7 | {"name": "You are what's wrong with humanity."} 8 | ] 9 | }, 10 | { 11 | "name": "Be silent.", 12 | "children": [ 13 | {"name": "Won't talk, eh? Into the brig with you!"} 14 | ] 15 | }, 16 | { 17 | "name": "No", 18 | "children": [ 19 | {"name": "Well, it's bullshit."} 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /examples/dialogue_tree.json: -------------------------------------------------------------------------------- 1 | [{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[],"name":"I deserved that."},{"children":[],"name":"Fuck you, buddy.\n"}],"name":"You're dead to me."}],"name":"sorta"},{"children":[{"children":[],"name":"Now we can be friends."}],"name":"No"},{"children":[{"children":[],"name":"Now we can be friends."}],"name":"Yes"}],"name":"Do you like playing legos?"}],"name":"I'm from Sacramento"},{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[],"name":"I deserved that."},{"children":[],"name":"Fuck you, buddy.\n"}],"name":"You're dead to me."}],"name":"sorta"},{"children":[{"children":[],"name":"Now we can be friends."}],"name":"No"},{"children":[{"children":[],"name":"Now we can be friends."}],"name":"Yes"}],"name":"Do you like playing legos?"}],"name":"I'm from Sacramento"}],"name":"Then why do you say hella all the time?"}],"name":"I'm from NYC"}],"name":"Where do you come from?"}] -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Convo.js 2 | ===== 3 | 4 | Convo is a tiny conversation tree interface in Node.js 5 | 6 | What it do 7 | ---------------------------- 8 | 9 | * Runs a JSON representation of a conversation tree as a multiple-choice dialog, Adventure Game style 10 | * check out the examples directory for what the format looks like 11 | * there's also a macruby script provided (in /script) that will take a hierarchical graph from Omnigraffle and turn it into the correct JSON 12 | * with convo, adventure game dialog is you! 13 | * Nothing else 14 | 15 | How it run 16 | ---------------------------- 17 | 18 | First install dependencies: 19 | `npm install` 20 | 21 | Then pass it a JSON file: 22 | `node convo examples/dialogue_tree.json` 23 | 24 | You can then either type you responses out, or enter in the corresponding digit. 25 | 26 | Generate your own dialog trees 27 | ---------------------------- 28 | 29 | * In omnigraffle, make a new doc from the "hierarchical" template. 30 | * Make sure you have MacRuby installed (it is a Ruby for Scottish people) 31 | * `macruby script/graffle2json` 32 | * the script will pull the data out of the foremost document open in graffle- no file paths required! 33 | * you'll find your translated JSON file in the convo root dir -------------------------------------------------------------------------------- /examples/jackets.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "children": [ 4 | { 5 | "children": [ 6 | { 7 | "children": [], 8 | "name": "Get lost!" 9 | } 10 | ], 11 | "name": "I'm a migty pirate!" 12 | }, 13 | { 14 | "children": [ 15 | { 16 | "children": [ 17 | { 18 | "children": [ 19 | { 20 | "children": [], 21 | "name": "I'll take 170 million." 22 | } 23 | ], 24 | "name": "2 bucks" 25 | }, 26 | { 27 | "children": [], 28 | "name": "149 dollars" 29 | } 30 | ], 31 | "name": "How much?" 32 | } 33 | ], 34 | "name": "Just selling these fine leather jackets." 35 | } 36 | ], 37 | "name": "What's yr business, stranger?" 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /examples/simple.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "What's yr business, stranger?", 4 | "children": [ 5 | { 6 | "name": "Just selling these fine leather jackets.", 7 | "children": [ 8 | { 9 | "name": "Get lost!", 10 | "children": [] 11 | } 12 | ] 13 | }, 14 | { 15 | "name": "I'm a migty pirate!", 16 | "children": [ 17 | { 18 | "children": [ 19 | { 20 | "children": [ 21 | { 22 | "children": [], 23 | "name": "I'll take 170 million." 24 | } 25 | ], 26 | "name": "2 bucks" 27 | }, 28 | { 29 | "children": [], 30 | "name": "149 dollars" 31 | } 32 | ], 33 | "name": "How much?" 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /script/graffle2json.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/macruby 2 | 3 | framework "ScriptingBridge" 4 | require 'json' 5 | 6 | class GraffleConverter 7 | def initialize 8 | @graffle = SBApplication.applicationWithBundleIdentifier("com.omnigroup.OmniGraffle") 9 | end 10 | 11 | def to_hash 12 | @shape_list = [] 13 | 14 | @graffle.windows[0].document.canvases[0].layers[0].shapes.select do |s| 15 | @shape_list << s 16 | s.incomingLines.length == 0 and s.outgoingLines.length > 1 17 | end.compact.collect { |root| process_node(root) } 18 | end 19 | 20 | # ========== 21 | # { 22 | # 'name':'node name', 23 | # 'children': [ 24 | # {...}, {...} 25 | # ] 26 | # } 27 | # ========== 28 | 29 | private 30 | def process_node(shape) 31 | puts shape.text.get 32 | raise ArgumentError, "No shape passed" unless shape 33 | 34 | children = [] 35 | 36 | shape.outgoingLines.each do |line| 37 | # destination is a graphic, not a shape, was having some issues working with shapes 38 | next_shape = @shape_list.detect { |d| d.valueForKey("id") == line.destination.valueForKey("id") } 39 | children << process_node(next_shape) 40 | end 41 | 42 | { :children => children, :name => shape.text.get.to_s } 43 | end 44 | end 45 | 46 | json = GraffleConverter.new.to_hash.to_json 47 | File.open('new_convo.json', 'w') {|f| f.write json } 48 | -------------------------------------------------------------------------------- /test/convo-test.js: -------------------------------------------------------------------------------- 1 | // convo-test.js 2 | 3 | var path = require('path'), 4 | vows = require('vows'), 5 | assert = require('assert'), 6 | gently = new (require('gently')), 7 | winston = require('winston'), 8 | convo = require('convo') 9 | 10 | vows.describe('Convo').addBatch({ 11 | '.askQuestions': { 12 | topic : [{ 13 | "name": "What is yr business, stranger?", 14 | "children": [{"name": "Whatsit to you, copper?", "children": []}] 15 | }], 16 | 17 | 18 | 'passes an Array containing a question object to the prompt': function (convoData) { 19 | gently.expect(convo.prompt, 'get', function(msg) { 20 | assert.isArray(msg) 21 | var question = msg[0] 22 | 23 | assert.isObject(question) 24 | assert.match(question.name, /What is yr business, stranger?/) 25 | assert.match(question.message, /What is yr business, stranger?/) 26 | assert.match(question.message, /Whatsit to you, copper?/) 27 | }); 28 | 29 | convo.askQuestions(convoData[0]) 30 | } 31 | }, 32 | 33 | 'interacting with the prompt': { 34 | topic: function () { 35 | winston.info('These prompt tests are interactive'); 36 | winston.info('Not following instructions will result in test failure'); 37 | 38 | convo.askQuestions({ 39 | "name": "What is yr business, stranger?", 40 | "children": [{"name": "Whatsit to you, copper?", "children": [{"name": "Yr under arrest."}]}] 41 | }) 42 | 43 | return null; 44 | }, 45 | 46 | ".askQuestions": { 47 | "when passed a node with no children": { 48 | topic: function () { 49 | winston.info('When prompted, enter: 1 [enter]'); 50 | gently.expect(convo, 'convoOver', function(msg) { 51 | assert.equal(msg.name, "Yr under arrest.") 52 | }) 53 | convo.prompt.getInput('1', this.callback); 54 | }, 55 | "gets user input and then ends the convo ": function (err, result) { 56 | assert.isNull(err); 57 | assert.equal(result, '1'); 58 | } 59 | } 60 | } 61 | } 62 | }).exportTo(module); 63 | 64 | 65 | -------------------------------------------------------------------------------- /lib/convo.js: -------------------------------------------------------------------------------- 1 | // convo.js 2 | // v 0.0.1 3 | 4 | require("colors") 5 | var _ = require("underscore") 6 | 7 | var convo = {VERSION: '0.0.1'} 8 | 9 | convo.prompt = require('prompt') 10 | convo.prompt.message = "\n" 11 | 12 | convo.askQuestions = function(n) { 13 | if (!this.prompt.started) this.prompt.start(); 14 | 15 | responses = _.map(n.children, function(answer, index) { 16 | return (index + 1 + ": ").blue + answer.name 17 | }) 18 | 19 | var question = { 20 | name: n.name, 21 | message: _.flatten([n.name.magenta, responses, '']).join('\n') 22 | } 23 | 24 | convo.prompt.get([question], function (err, result) { 25 | if (err) { return onErr(err) } 26 | var selection = result[n.name] 27 | 28 | // Is it a number, or are they typing in the full response? 29 | if (_.isNumber(+selection) && !_.isNaN(+selection)) { 30 | var choice = n.children[selection - 1] 31 | } else { 32 | var choice = n.children.find(function(i) { 33 | return i.name.trim() == selection 34 | }) 35 | } 36 | 37 | if (_.isObject(choice)) { 38 | var whatsNext = choice.children[0] 39 | 40 | if (whatsNext && whatsNext.children && whatsNext.children.length) { 41 | convo.askQuestions(whatsNext) 42 | } else { 43 | convo.convoOver(whatsNext) 44 | } 45 | } else { 46 | convoOver({name : "... that was not an option"}) 47 | } 48 | }) 49 | } 50 | 51 | convo.convoOver = function(lastNode) { 52 | if (lastNode && lastNode.name) { 53 | console.log(lastNode.name.magenta) 54 | } else { 55 | console.log("Game over, man".magenta) 56 | } 57 | return 1 58 | } 59 | 60 | convo.onErr = function(err) { 61 | console.log("ERROR!!".red, err) 62 | return 0 63 | } 64 | 65 | 66 | var isHeadless = false; 67 | if (typeof module !== 'undefined') { 68 | isHeadless = true; 69 | } 70 | 71 | if (!isHeadless) { 72 | var exports = convo 73 | var module = {} 74 | exports.mode = "browser" 75 | } else { 76 | exports.mode = "console" 77 | var fs = require('fs') 78 | var arguments = process.argv.splice(2) 79 | if(arguments[0]) { 80 | var conversation = JSON.parse(fs.readFileSync(arguments[0], 'utf8'))[0] 81 | } 82 | convo.askQuestions(conversation) 83 | } 84 | 85 | -------------------------------------------------------------------------------- /examples/dialogue_tree.graffle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ActiveLayerIndex 6 | 0 7 | ApplicationVersion 8 | 9 | com.omnigroup.OmniGraffle 10 | 138.33.0.157554 11 | 12 | AutoAdjust 13 | 14 | BackgroundGraphic 15 | 16 | Bounds 17 | {{0, 0}, {744, 811.93518}} 18 | Class 19 | SolidGraphic 20 | ID 21 | 2 22 | Style 23 | 24 | shadow 25 | 26 | Draws 27 | NO 28 | 29 | stroke 30 | 31 | Draws 32 | NO 33 | 34 | 35 | 36 | CanvasOrigin 37 | {0, 0} 38 | CanvasSize 39 | {744, 811.93518} 40 | ColumnAlign 41 | 1 42 | ColumnSpacing 43 | 36 44 | CreationDate 45 | 2012-01-27 02:01:21 +0000 46 | Creator 47 | Patrick Ewing 48 | DisplayScale 49 | 1 0/72 in = 1.0000 in 50 | FileType 51 | flat 52 | GraphDocumentVersion 53 | 8 54 | GraphicsList 55 | 56 | 57 | Class 58 | LineGraphic 59 | Head 60 | 61 | ID 62 | 1185 63 | 64 | ID 65 | 1187 66 | Points 67 | 68 | {580.47345, 580.4718} 69 | {598.0498, 615.86243} 70 | 71 | Style 72 | 73 | stroke 74 | 75 | HeadArrow 76 | FilledArrow 77 | LineType 78 | 1 79 | TailArrow 80 | 0 81 | 82 | 83 | Tail 84 | 85 | ID 86 | 19 87 | 88 | 89 | 90 | Class 91 | LineGraphic 92 | Head 93 | 94 | ID 95 | 1184 96 | 97 | ID 98 | 1186 99 | Points 100 | 101 | {537.83533, 580.37817} 102 | {502.39331, 615.95605} 103 | 104 | Style 105 | 106 | stroke 107 | 108 | HeadArrow 109 | FilledArrow 110 | LineType 111 | 1 112 | TailArrow 113 | 0 114 | 115 | 116 | Tail 117 | 118 | ID 119 | 19 120 | 121 | 122 | 123 | Bounds 124 | {{558.46155, 616.3103}, {113.3927, 68}} 125 | Class 126 | ShapedGraphic 127 | ID 128 | 1185 129 | Shape 130 | Rectangle 131 | Text 132 | 133 | Text 134 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 135 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 136 | {\colortbl;\red255\green255\blue255;} 137 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 138 | 139 | \f0\fs24 \cf0 I deserved that.} 140 | 141 | 142 | 143 | Bounds 144 | {{399.92432, 616.3103}, {125.51477, 79.0299}} 145 | Class 146 | ShapedGraphic 147 | ID 148 | 1184 149 | Shape 150 | Rectangle 151 | Text 152 | 153 | Text 154 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 155 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 156 | {\colortbl;\red255\green255\blue255;} 157 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 158 | 159 | \f0\fs24 \cf0 Fuck you, buddy.\ 160 | } 161 | 162 | 163 | 164 | Class 165 | LineGraphic 166 | Head 167 | 168 | ID 169 | 4 170 | 171 | ID 172 | 1181 173 | Points 174 | 175 | {326.82788, 92.389763} 176 | {360.51471, 127.91335} 177 | 178 | Style 179 | 180 | stroke 181 | 182 | HeadArrow 183 | FilledArrow 184 | LineType 185 | 1 186 | TailArrow 187 | 0 188 | 189 | 190 | Tail 191 | 192 | ID 193 | 3 194 | 195 | 196 | 197 | Class 198 | LineGraphic 199 | Head 200 | 201 | ID 202 | 19 203 | 204 | ID 205 | 25 206 | Points 207 | 208 | {566.25739, 481.67645} 209 | {566.25739, 523.17041} 210 | 211 | Style 212 | 213 | stroke 214 | 215 | HeadArrow 216 | FilledArrow 217 | LineType 218 | 1 219 | TailArrow 220 | 0 221 | 222 | 223 | Tail 224 | 225 | ID 226 | 17 227 | 228 | 229 | 230 | Class 231 | LineGraphic 232 | Head 233 | 234 | ID 235 | 18 236 | 237 | ID 238 | 24 239 | Points 240 | 241 | {256.15234, 481.58694} 242 | {280.95245, 517.25897} 243 | 244 | Style 245 | 246 | stroke 247 | 248 | HeadArrow 249 | FilledArrow 250 | LineType 251 | 1 252 | TailArrow 253 | 0 254 | 255 | 256 | Tail 257 | 258 | ID 259 | 13 260 | 261 | 262 | 263 | Class 264 | LineGraphic 265 | Head 266 | 267 | ID 268 | 18 269 | 270 | ID 271 | 23 272 | Points 273 | 274 | {376.17621, 481.52722} 275 | {339.82376, 517.32062} 276 | 277 | Style 278 | 279 | stroke 280 | 281 | HeadArrow 282 | FilledArrow 283 | LineType 284 | 1 285 | TailArrow 286 | 0 287 | 288 | 289 | Tail 290 | 291 | ID 292 | 16 293 | 294 | 295 | 296 | Class 297 | LineGraphic 298 | Head 299 | 300 | ID 301 | 17 302 | 303 | ID 304 | 22 305 | Points 306 | 307 | {454.04013, 394.26456} 308 | {519.66345, 430.27734} 309 | 310 | Style 311 | 312 | stroke 313 | 314 | HeadArrow 315 | FilledArrow 316 | LineType 317 | 1 318 | TailArrow 319 | 0 320 | 321 | 322 | Tail 323 | 324 | ID 325 | 11 326 | 327 | 328 | 329 | Class 330 | LineGraphic 331 | Head 332 | 333 | ID 334 | 16 335 | 336 | ID 337 | 21 338 | Points 339 | 340 | {402.25739, 394.52399} 341 | {402.25739, 430.01791} 342 | 343 | Style 344 | 345 | stroke 346 | 347 | HeadArrow 348 | FilledArrow 349 | LineType 350 | 1 351 | TailArrow 352 | 0 353 | 354 | 355 | Tail 356 | 357 | ID 358 | 11 359 | 360 | 361 | 362 | Class 363 | LineGraphic 364 | Head 365 | 366 | ID 367 | 13 368 | 369 | ID 370 | 20 371 | Points 372 | 373 | {350.47464, 394.26456} 374 | {284.85132, 430.27734} 375 | 376 | Style 377 | 378 | stroke 379 | 380 | HeadArrow 381 | FilledArrow 382 | LineType 383 | 1 384 | TailArrow 385 | 0 386 | 387 | 388 | Tail 389 | 390 | ID 391 | 11 392 | 393 | 394 | 395 | Bounds 396 | {{495.25739, 523.67035}, {142, 56.353577}} 397 | Class 398 | ShapedGraphic 399 | ID 400 | 19 401 | Shape 402 | Rectangle 403 | Text 404 | 405 | Text 406 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 407 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 408 | {\colortbl;\red255\green255\blue255;} 409 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 410 | 411 | \f0\fs24 \cf0 You're dead to me.} 412 | 413 | 414 | 415 | Bounds 416 | {{216.23001, 517.67035}, {177, 68}} 417 | Class 418 | ShapedGraphic 419 | ID 420 | 18 421 | Shape 422 | Rectangle 423 | Text 424 | 425 | Text 426 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 427 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 428 | {\colortbl;\red255\green255\blue255;} 429 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 430 | 431 | \f0\fs24 \cf0 Now we can be friends.} 432 | 433 | 434 | 435 | Bounds 436 | {{493.00781, 430.51788}, {146.49915, 50.658569}} 437 | Class 438 | ShapedGraphic 439 | ID 440 | 17 441 | Shape 442 | Rectangle 443 | Text 444 | 445 | Text 446 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 447 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 448 | {\colortbl;\red255\green255\blue255;} 449 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 450 | 451 | \f0\fs24 \cf0 sorta} 452 | 453 | 454 | 455 | Bounds 456 | {{329.00781, 430.51788}, {146.49915, 50.658569}} 457 | Class 458 | ShapedGraphic 459 | ID 460 | 16 461 | Shape 462 | Rectangle 463 | Text 464 | 465 | Text 466 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 467 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 468 | {\colortbl;\red255\green255\blue255;} 469 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 470 | 471 | \f0\fs24 \cf0 No} 472 | 473 | 474 | 475 | Bounds 476 | {{165.00781, 430.51788}, {146.49915, 50.658569}} 477 | Class 478 | ShapedGraphic 479 | ID 480 | 13 481 | Shape 482 | Rectangle 483 | Text 484 | 485 | Text 486 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 487 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 488 | {\colortbl;\red255\green255\blue255;} 489 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 490 | 491 | \f0\fs24 \cf0 Yes} 492 | 493 | 494 | 495 | Class 496 | LineGraphic 497 | Head 498 | 499 | ID 500 | 11 501 | 502 | ID 503 | 12 504 | Points 505 | 506 | {402.25739, 212.76947} 507 | {402.25742, 337.17041} 508 | 509 | Style 510 | 511 | stroke 512 | 513 | HeadArrow 514 | FilledArrow 515 | LineType 516 | 1 517 | TailArrow 518 | 0 519 | 520 | 521 | Tail 522 | 523 | ID 524 | 4 525 | 526 | 527 | 528 | Bounds 529 | {{339.5, 337.67041}, {125.51477, 56.353577}} 530 | Class 531 | ShapedGraphic 532 | ID 533 | 11 534 | Shape 535 | Rectangle 536 | Text 537 | 538 | Text 539 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 540 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 541 | {\colortbl;\red255\green255\blue255;} 542 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 543 | 544 | \f0\fs24 \cf0 Do you like playing legos?} 545 | 546 | 547 | 548 | Class 549 | LineGraphic 550 | Head 551 | 552 | ID 553 | 4 554 | 555 | ID 556 | 1169 557 | Points 558 | 559 | {287.74179, 248.22823} 560 | {339.496, 212.54883} 561 | 562 | Style 563 | 564 | stroke 565 | 566 | HeadArrow 567 | FilledArrow 568 | LineType 569 | 1 570 | TailArrow 571 | 0 572 | 573 | 574 | Tail 575 | 576 | ID 577 | 6 578 | 579 | 580 | 581 | Class 582 | LineGraphic 583 | Head 584 | 585 | ID 586 | 6 587 | 588 | ID 589 | 9 590 | Points 591 | 592 | {195.25601, 212.69475} 593 | {217.13788, 248.08447} 594 | 595 | Style 596 | 597 | stroke 598 | 599 | HeadArrow 600 | FilledArrow 601 | LineType 602 | 1 603 | TailArrow 604 | 0 605 | 606 | 607 | Tail 608 | 609 | ID 610 | 5 611 | 612 | 613 | 614 | Class 615 | LineGraphic 616 | Head 617 | 618 | ID 619 | 5 620 | 621 | ID 622 | 7 623 | Points 624 | 625 | {248.7475, 92.378746} 626 | {212.84959, 127.92204} 627 | 628 | Style 629 | 630 | stroke 631 | 632 | HeadArrow 633 | FilledArrow 634 | LineType 635 | 1 636 | TailArrow 637 | 0 638 | 639 | 640 | Tail 641 | 642 | ID 643 | 3 644 | 645 | 646 | 647 | Bounds 648 | {{164.76242, 248.51201}, {146.49915, 68}} 649 | Class 650 | ShapedGraphic 651 | ID 652 | 6 653 | Shape 654 | Rectangle 655 | Text 656 | 657 | Text 658 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 659 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 660 | {\colortbl;\red255\green255\blue255;} 661 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 662 | 663 | \f0\fs24 \cf0 Then why do you say hella all the time?} 664 | 665 | 666 | 667 | Bounds 668 | {{98.023987, 128.26947}, {142, 84}} 669 | Class 670 | ShapedGraphic 671 | ID 672 | 5 673 | Shape 674 | Rectangle 675 | Text 676 | 677 | Text 678 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 679 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 680 | {\colortbl;\red255\green255\blue255;} 681 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 682 | 683 | \f0\fs24 \cf0 I'm from NYC} 684 | 685 | 686 | 687 | Bounds 688 | {{339.5, 128.26947}, {125.51477, 84}} 689 | Class 690 | ShapedGraphic 691 | ID 692 | 4 693 | Shape 694 | Rectangle 695 | Text 696 | 697 | Text 698 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 699 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 700 | {\colortbl;\red255\green255\blue255;} 701 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 702 | 703 | \f0\fs24 \cf0 I'm from Sacramento} 704 | 705 | 706 | 707 | Bounds 708 | {{197.66612, 12.997046}, {182.69174, 79.0299}} 709 | Class 710 | ShapedGraphic 711 | FontInfo 712 | 713 | Font 714 | Helvetica 715 | Size 716 | 12 717 | 718 | ID 719 | 3 720 | Shape 721 | Rectangle 722 | Text 723 | 724 | Text 725 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 726 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 727 | {\colortbl;\red255\green255\blue255;} 728 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 729 | 730 | \f0\fs24 \cf0 Where do you come from?} 731 | 732 | 733 | 734 | GridInfo 735 | 736 | GuidesLocked 737 | NO 738 | GuidesVisible 739 | YES 740 | HPages 741 | 2 742 | ImageCounter 743 | 3 744 | KeepToScale 745 | 746 | Layers 747 | 748 | 749 | Lock 750 | NO 751 | Name 752 | Layer 1 753 | Print 754 | YES 755 | View 756 | YES 757 | 758 | 759 | LayoutInfo 760 | 761 | Animate 762 | NO 763 | LineLength 764 | 0.4643835723400116 765 | circoMinDist 766 | 18 767 | circoSeparation 768 | 0.0 769 | layoutEngine 770 | dot 771 | neatoSeparation 772 | 0.0 773 | twopiSeparation 774 | 0.0 775 | 776 | LinksVisible 777 | NO 778 | MagnetsVisible 779 | NO 780 | MasterSheets 781 | 782 | ModificationDate 783 | 2012-01-28 19:39:29 +0000 784 | Modifier 785 | Patrick Ewing 786 | NotesVisible 787 | NO 788 | Orientation 789 | 2 790 | OriginVisible 791 | NO 792 | OutlineStyle 793 | Basic 794 | PageBreaks 795 | NO 796 | PrintInfo 797 | 798 | NSBottomMargin 799 | 800 | float 801 | 41 802 | 803 | NSHorizonalPagination 804 | 805 | int 806 | 0 807 | 808 | NSLeftMargin 809 | 810 | float 811 | 18 812 | 813 | NSPaperSize 814 | 815 | coded 816 | BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== 817 | 818 | NSPrintReverseOrientation 819 | 820 | int 821 | 0 822 | 823 | NSRightMargin 824 | 825 | float 826 | 18 827 | 828 | NSTopMargin 829 | 830 | float 831 | 18 832 | 833 | 834 | PrintOnePage 835 | 836 | ReadOnly 837 | NO 838 | RowAlign 839 | 1 840 | RowSpacing 841 | 36 842 | SheetTitle 843 | Canvas 1 844 | SmartAlignmentGuidesActive 845 | YES 846 | SmartDistanceGuidesActive 847 | YES 848 | UniqueID 849 | 1 850 | UseEntirePage 851 | 852 | VPages 853 | 2 854 | WindowInfo 855 | 856 | CurrentSheet 857 | 0 858 | ExpandedCanvases 859 | 860 | FitInWindow 861 | 862 | Frame 863 | {{10, -17}, {972, 850}} 864 | ListView 865 | 866 | OutlineWidth 867 | 295 868 | RightSidebar 869 | 870 | Sidebar 871 | 872 | SidebarWidth 873 | 138 874 | VisibleRegion 875 | {{1.0958164, 1.0958164}, {741.86768, 810.90411}} 876 | Zoom 877 | 0.91256159543991089 878 | ZoomValues 879 | 880 | 881 | Canvas 1 882 | 0.0 883 | 1 884 | 885 | 886 | 887 | saveQuickLookFiles 888 | YES 889 | 890 | 891 | --------------------------------------------------------------------------------