ArchNadeom, Keeper Of Records.
Stardate #273.
Sumara gazed out the observation window.
The last weeks had been bloody.
Top ace captains of every fleet raged ruthless war on each other. Brazenly trespassing onto other fleet territories. Preying on weaker ships. Plundering resources and trophy souvenirs to adorn their hulls. Settling disputes at the end of a gun.
Deep blood feuds were born.
The intergalactic news recognized the top three captains. Those whose warships were most garishly decorated in the trophies of their defeated enemies.
1st. thunder_kiss_65
2nd. 七宇
3rd. Prinz_Eugen
All were of the fleet Elder Drivers.
All featuring their own pictcasts. Weapons unholstered. Teeth grinning broad-toothed smiles. Standing triumphant over the smoldering ruins of some unfortunate captain. Like whalers leaning proudly against their harpoons. Their biggest catch hooked and pulled up alongside their ship.
Contemptuous. Flagrant. Cruel.
It was a galaxy thirsty for war.
Having routed Victrix Mortalis, Wolfpack made a good standing for themselves. Solidly securing their own foothold in the galaxy. They were surpassed only by the Dark Matter Heroes and Elder Drivers.
Wolfpack even gave a strong account of themselves among the top captains. One of the pack’s new recruits, OliveOyl, placed herself in 5th. Despite being hospitalized after a ruptured bulkhead smashed into her shoulder and shattered her arm. Lord Commander WarWolff was close behind at 8th.
Wolfpack was even strong enough to send aid to Dark Matter Heroes.
Following friendly discussions between Caxy and one of the leaders of Dark Matter Heroes, Citizenband, they reached an agreement.
RollFizelBeef, Myke, SCVsUnion, Dan_the_man181, and JeffLA would all go over to lend a hand to their new allies. Helping them fend off repeated incursions by the Elder Drivers.
Caxy even brought his own ship out of port and dusted off the console to look over omega pack during the last days of the cycle.
It was an exciting time for Wolfpack. One of growing power. They were strong enough now to use their own fleet as leverage to determine the fate of the galaxy.
Wolfpack would soon make a reckoning.
Sumara had planted her ship along one of Wolfpack’s borders. Protecting their fleet with a bristling armament of firepower.
Setting up a defensive perimeter in space is not easy. Ships are isolated, often light years apart, and can be scanned from a sector away.
Trying to escape a battle usually ends in catastrophe. There is a split second before warp jump kicks in where your ship is completely exposed to enemy fire. If the enemy aims a well-placed shot at the warp drive, then kablooey! The warp field collapses around the hull, crushing your ship within it.
Even sending a distress signal is pointless. Help could never reach you in time. The best you can hope for is that someone sends a shop-vac and good cleanup crew. Or vultures to pick up the scraps.
Space battles are fatalistic. Either your ship survives. Or it becomes a trophy adorning another ship’s wall.
Sumara was attacked first by Cloggster of Clan Zaki. It was a brutal exchange of weapons, but Sumara came out on top. She left the wracked hulk of his ship smoking not far from her position. A warning against further adversaries.
Then she was attacked by 麦道大牛牛.
Then by Quansei, Mdff8, and KuKu桑 .
Single-handedly, she defeated them all. Lining the blackened husks of their broken ships in front of her. Like heads mounted on the pickets of a castle wall.
Instead of warding off would-be attackers, the more victories she accumulated then the fiercer she was attacked. A mighty fire-belching dragon that every captain intent on proving his valor was keen to slay.
Sumara was a fierce fighter. One of Wolfpack’s best. Her succession of repeated defenses won her recognition across the galaxy, claiming her top prize in the Wolfpack’s Alpha Wolf Contest.
As well as earning her honorable mention in the Pillaging Scourge & Looting Lunatics starlog contest.
She was a legend.
Sumara looked out the observation window.
Her ship orbited the planet Xeanus in the border sector. A white star shone around the edge of the planet’s sphere. Catching the dunes of desert gold along its surface, under the aqua blue atmosphere. It was breathtaking.
She hadn’t forgotten why she had become a starship captain. Launching through the atmosphere at speeds upwards of Mach 23. The galaxy opening before her. Like walking out of a cave through a waterfall. Flying among the stars.
Invigorating. Untethered. Free.
Just look at that view.
“Sir, letters have arrived from fleet headquarters.”
Sumara leaned back in the captain’s chair. Kicking her feet up on the console and luxuriously sinking in the soft fur rug draped across the back. She grabbed the hip flask from her belt.
Roborob set the letters down in a neat stack next to her heel. Careful to not make eye contact. Focusing on some undefined point just over her shoulder. Deliberately looking somewhere else.
Sumara watched his eyes. Swirling the liquid around in her flask. Sloshing some unidentifiable object around within. Then she took a swig.
Roborob blanched visibily, “I’ll leave you to it, sir.” He saluted, then speedily exited the bridge.
Sumara smirked. The joke never got old.
She was much loved in the pack. As well as among other fleets in the galaxy. Winning herself the nickname Smelzy among her closest friends.
She was aware of her growing popularity. But having championed the intergalactic contests, her fame was reaching unprecedented proportions. Now she was receiving fan letters of undying love and loyalty from the pack?
“Hmmmm, poetry. The cat sat on a mat inside a vat with a rat. This should prove interesting….”
 Better run
Bloody feasts await.
–fritz
Drink from me
Lips of red
Moonlight on the pale skin
Live for life
Love through death
Drink from me an eternal kiss
–ArchNadeom
Smelzy the Wolf Lord
Counting her bux and laughing.

Восходит звезда.
All the enemies fell down
Like the autumn leaves.
The star is rising.


(Chicken cubes sautéed with spicy sauce, spiked with jalapenos and toasted cashews)
$11.9
Prawns 65
(Jumbo Shrimp marinated with Chettinad masala, a Kalpasi Specialty)
$10
Fish 65
(Boneless cubes of fish marinated with exotic spices and fried)
$9.5
Pondicherry Prawn Vadai
(Fresh and crispy snack made with Shrimp, herbs, and spices)
$9.9
Thali - Lunch-Only Special
Balanced meal. Enjoy a blend of dishes in one single Thali - Served with protein-rich Dal, Chapati, Kootu/Poriyal, Sambar, Rasam, Rice, Whole Yogurt, Pappad, Dessert of the day and a Chefs Vegetable Curry or a Meat curry – No substitutions
Vegetarian Thali
$12
Egg Thali
$12
Chicken Thali
$13
Fish Thali
$14
Mutton Thali
$14.5
Chettinad Biriyani Special
Traditionally prepared, aromatic rice, flavored with cloves, cinnamon, cardamon, bay leaf, coriander, mint, ginger, garlic and onions
Vegetarian Biriyani
$11.9
Chicken Biriyani
$12.9
Mutton Biriyani
$13.9
Curd Rice
$9.9
Kalpasi Noodles Special
Vegetarian Eggless Noodles
$9.9
Chicken Noodles
$11.9
Egg Noodles
$10.9
Vegetarian Signature Entrees
All entrees are served with steamed rice - No substitutions
Poondu Kulambu
(Selected peeled whole Garlic, and potatoes cooked in hot tamarind sauce, a Kalpasi Specialty)
$12
Eggplant Curry
(Fresh Indian Eggplant curry simmered in tamarind sauce and house spices)
$11.5
Vegetable Chettinad
(Chettinad style curry prepared with mixed fresh vegetables and dry roasted aromatic spices)
$12
Dal Tadka
(Moong dal boiled and cooked with onion, tomatoes and traditional Indian spices)
$10
Mixed Vegetable Kurma
(Mixed vegetables of carrot, cauliflower, peas, potato, and beans simmered in coconut based gravy)
$11
Vada Curry
(Chickpeas simmered with special ground masala, a Kalpasi Specialty)
$10.5
Chana Masala
(Chickpeas and tomatoes simmered with a mixture of fried garlic, ginger, and onion)
$11
Malai Palak Paneer
(Fresh spinach cooked with cottage cheese)
$12
Paneer Tikka Masala
(Fresh grilled paneer with tomato creamy gravy)
$12.5
Kadai Paneer
(Soft chunks of cottage cheese and bell pepper immersed in a spicy tomato-onion based masala)
$12
Mutter Paneer
(Cubes of cottage cheese and baby green peas cooked in a creamy onion & tomato sauce)
$12.5
Non-Vegetarian Signature Entrees
All entrees are served with steamed rice - No substitutions
Malabar Fish Curry
(Tilapia fish fillets specialty with authentic Malabari flavors)
$13
Kalpasi Meen Kulambu
(Flavorful authentic Chettinad King Fish curry)
$14
Meen Varuval / Grilled Fish
(Fresh sea catch fish, marinated in Chettinad spices, tawa grilled, a Kalpasi Specialty)
$15.5
Prawns / Shrimp Specials
Chettinad prawns pepper masala 14 Malabar shrimp Curry
$14
Chettinad Egg Specials
Egg Curry 11 Egg Pepper Masala
$11.5
Virdhunagar Koli Curry
(Tender pieces of chicken marinated and cooked in authentic roasted coconut and pepper)
$12
Chettinad Koli Roast
(Chicken with bones, roasted in black pepper and fresh ground masalas, a Kalpasi Specialty)
$14.5
Chicken Chettinad
(Spicy chicken marinated in chef’s handmade masala and roasted to taste)
$13.5
Tikka Masala - UK’s favourite
(Boneless meat cooked in rich tomato gravy, spices and butter)
Chicken Tikka Masala
$13.5
Shrimp Tikka Masala
$14
Salmon Tikka Masala
$14.5
Lamb Tikka Masala
$14.5
Vindaloo
(a Goan style, combination of hot peppers, meat and house spices) Chicken Vindaloo 13.5 Shrimp Vindaloo 14 Lamb Vindaloo
$14.5
Spinach Saag Specials
(Boneless meat simmered in Spinach, tasty, nutritious and healthy)
Chicken Saag
$13.5
Lamb Saag
$14.5
Chettinad Goat Specials
(Our Chef’s special, a hearty dish cooked in a melange of spices and goat meat with bones)
Goat Curry
$14
Goat Chukka
$14.9
Mutton Chukka Varuval
(Boneless, Chettinad dish made with tender pieces of mutton and special thick gravy you’ll fall in love with!)
$15.9
Tandoor from Clay Pot Oven
Served sizzling hot over a bed of sautéed cabbage, onions, fresh lemons, and mint chutney
Paneer Tikka Kebab
(Soft, juicy chunks of cottage cheese marinated in spices and cooked in clay pot oven)
$15.5
Tandoori Chicken
Chicken marinated in a mixture of yogurt, garlic, ginger, selected spices and grilled in the tandoor, a Kalpasi Specialty
Half chicken
$15.5
Full chicken
$20.5
Chicken Tikka Kebab
(A classic Indian dish - Chicken marinated in yogurt and herbs with mild spices)


{% extends "base_site.html" %} {% block doctype %} {% endblock %} {% block html_attributes %}xmlns=http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml"{% endblock %} {% block tag_head %} {% block tag_stylesheets %} {% endblock %} {% endblock %} {% block tag_body %}
Hi, I'm Kumaar and I'm writing a book about you. Please help me out by suggesting titles for the book, voting for your favorite celebrities whos stories you want featured in the book, or by adding your own story.


Know More About Us
Who Are We
Natural palettes was created to help artist find unique color palettes, it's also a calming place where I aim for it to be welcoming to everyone. Each palette is created by hand in photoshop, with no help generating the palette.
What We Do
I choose each and every color for how well it coordinates with the other colors for the most aesthetically pleasing color palettes.
Achievements
Started in 2013, this blog has grown to over 150,000 followers, and I can't thank you enough for the continued support. All palettes created are protected by copyright. Please do not repost them here or to any other website without permission.
Service Area
Everything, every little detail that is a part of your website design is important and impacts the user experience in some way. One of the things that easily gets overlooked is the color scheme because people often underestimate it. Choosing the right website color schemes might not seem like much, but it can get you a long way. Cool color schemes will make the user feel more welcome and comfortable on your website while enhancing the overall user experience.


--- layout: post date: 2012-10-03 time: "09:00:00" authors: ["Greg Wilson"] title: Best Practices for Scientific Computing tags: ["Content", "Research"] ---
The following pre-print is now available on arXiv:
D.A. Aruliaha, C. Titus Brownb, Neil P. Chue Hongc, Matt Davisd, Richard T. Guye, Steven H.D. Haddockf, Katy Huffg, Ian Mitchellh, Mark Plumbleyi, Ben Waughj, Ethan P. Whitek, Greg Wilsonl, and Paul Wilsong.
aUniversity of Ontario Institute of Technology, bMichigan State University, cSoftware Sustainability Institute, dSpace Telescope Science Institute, eUniversity of Toronto, fMonterey Bay Aquarium Research Institute, gUniversity of Wisconsin, hUniversity of British Columbia, iQueen Mary University London, jUniversity College London, kUtah State University, and lSoftware Carpentry.
AbstractScientists spend an increasing amount of time building and using software. However, most scientists are never taught how to do this efficiently. As a result, many are unaware of tools and practices that would allow them to write more reliable and maintainable code with less effort. We describe a set of best practices for scientific software development that have solid foundations in research and experience, and that improve scientists' productivity and the reliability of their software.


About Us
Sibling Connections' mission is to support the creation of enduring family relationships and community connections for sisters and brothers separated by the foster care system in Massachusetts.
Our vision is for every child who is removed from their home and placed in the foster care system to maintain their sibling bond and be rooted in and surrounded by a community caring people invested in their health and well being.
A little more about what we do...
Sibling Connections is the only organization in Massachusetts designed to strengthen the sibling bond of children separated by foster care. While the sibling relationship is the longest, and one of the most important, relationships most people have in their lives, this is especially true for children who are removed from their families because of abuse or neglect. In many instances, a brother or sister might literally be the only constant relationship in a child’s life.


This is how you embed an HTTP Cat using web components.
<img is="http-cat" status="404">
And it looks like this:
API
Available attributes
status
- The HTTP status code to show the related cat image
It supports all standard img
element attributes (don't forget alt
!).


2 new members elected to Pulitzer Prize board
NEW YORK (AP) - The Pulitzer Prize Board has elected two new members to its board.
Columbia University, which administers the prizes, announced Thursday that Carlos Lozada and David Remnick are joining the 19-member board composed of leading journalists and news executives across the country.
Lozada, an associated editor and book critic for The Washington Post, received the Pulitzer Prize for Criticism this year for his essays and reviews on books addressing government and the American experience.
Remnick has been the editor of The New Yorker since 1998 and wrote for the news magazine as a staff writer, covering issues on Russia, the Middle East and Europe since 1992. He has won four Pulitzers.
The board hands out the best-known awards in journalism and members serve a maximum of nine years in three-year terms.
Sign up for Daily Newsletters
Copyright © 2019 The Washington Times, LLC.
Please read our comment policy before commenting.


Elder Casian:
So you believe you are the one? Very well...
If you are so positive that yours is the best path, test yourself!
"What are you talking about?"


Group 1
Remember: you are pretending to be a robot! Follow the instructions closely, even if they seem unnecessary.
- Start your timer
- Look at each row one by one; cross out the row if the Number Sold is ≤ 20,000,000
- Look at each row one by one again; if the row is not crossed out, write the decade of the Release Date in the "Decades" scratch sheet if it is not already written down
- Now you have a list of all the unique decades in the "Decades" scratch sheet!
- For each decade you wrote down:
- Write the decade and the number 0 as a row in the "Counters" scratch sheet
- Look at each row in the list of video games; if the row is not crossed out and the Release Date is in the same decade, then add 1 to the decade's number
- Read through the "Counters" scratch sheet and write the decade with the biggest counter in the "Result" table below.
- Write down how long it took and let Eugene know by raising your hand
| Result | How many minutes did your group take? |
| | |
Group 2
Remember: you are pretending to be a robot! Follow the instructions closely, even if they seem unnecessary.
- Start your timer
- Look at each row one by one; cross out the row if the Number Sold is ≤ 20,000,000
- Look at each row one by one again; if the row is not crossed out, then:
- If the decade of the row's Release Date isn't on the "Counters" scratch sheet, write it down in a new row, and write 0 for its counter value.
- Add 1 to the decade's counter
- Read through the "Counters" scratch sheet and write the decade with the biggest counter in the "Result" table below.
- Write down how long it took and let Eugene know by raising your hand
| Result | How many minutes did your group take? |
| | |
Group 3
Remember: you are pretending to be a robot! Follow the instructions closely, even if they seem unnecessary.
- Give each member in your 5-person group one of the Data sheets, a copy of the "Counters" scratch sheet, and a copy of these instructions.
- Each member should do the following
- Look at each row one by one; cross out the row if the Number Sold is ≤ 20,000,000
- Look at each row one by one again; if the row is not crossed out, then:
- If the decade of the row's Release Date isn't on the "Counters" scratch sheet, write it down in a new row, and write 0 for its counter value.
- Add 1 to the decade's counter
- Once everyone in your group is done, go through each member's "Counters" scratch sheet and
- copy each row to the "Master Counters" scratch sheet.
- If the decade already exists, add their counter value together and update the row in the "Moster Counters" scratch sheet
- Read through the "Master Counters" scratch sheet and write the decade with the biggest counter in the "Result" table below.
- Write down how long it took and let Eugene know by raising your hand
| Result | How many minutes did your group take? |
| | |
Group 4
Remember: you are pretending to be a robot! Follow the instructions closely, even if they seem unnecessary.
- Give each member in your 10-person group one of the Data sheets, a copy of the "Counters" scratch sheet, and a copy of these instructions.
- Each member should do the following
- Look at each row one by one; cross out the row if the Number Sold is ≤ 20,000,000
- Look at each row one by one again; if the row is not crossed out, then:
- If the decade of the row's Release Date isn't on the "Counters" scratch sheet, write it down in a new row, and write 0 for its counter value.
- Add 1 to the decade's counter
- Once everyone in your group is done, go through each member's "Counters" scratch sheet and
- copy each row to the "Master Counters" scratch sheet.
- If the decade already exists, add their counter value together and update the row in the "Moster Counters" scratch sheet
- Read through the "Master Counters" scratch sheet and write the decade with the biggest counter in the "Result" table below.
- Write down how long it took and let Eugene know by raising your hand
| Result | How many minutes did your group take? |
| | |
Group 5
Remember: you are pretending to be a robot! Follow the instructions closely, even if they seem unnecessary.
- The Index data sheet contains whether a game sold more than 20,000,000 games, the Decade the game was sold, and the list of ids for the games.
- Look through the rows in the Index one by one:
- if Number Sold is not more than 20,000,000, then cross it out
- if Number Sold is more than 20,000,000, then write down the number of Ids in the row
- Write down the decade with the biggest number of ids in the "Result" table below
- Write down how long it took and let Eugene know by raising your hand
| Result | How many minutes did your group take? |
| | |


Search
EXPLORE is an integrated library system (ILS) that is operated by the MOBIUS Consortium. EXPLORE is shared by the four members of the Saint Louis Research Library Consortium (SLRLC). The ILS uses Sierra software, developed by Innovative Interfaces.
SLRLC began in 2003 with generous support from the Andrew W. Mellon Foundation. The founding members are the Missouri History Museum, the Saint Louis Art Museum and the Missouri Botanical Garden. Goldfarb School of Nursing joined in 2010. In 2014 SLRLC joined the MOBIUS Consortium as the EXPLORE cluster.


The Grimms' Fairy Tale
Illustrated by Lucy Gow
Once upon a time a queen sat sewing by a window made of ebony wood.
She pricked her finger and blood fell on the snow. She wished she had a baby with hair as black as ebony, lips as red as blood, and skin as white as snow.
The queen’s wish came true. They called the baby Snow White.
Sadly, the queen died not long after.
The king remarried.
His new wife had a magic mirror that told the truth.Each day, she asked the mirror:
“Mirror, mirror on the wall,who is the fairest one of all?”
Each day the mirror answered, “you are.”
Until one day the mirror said …
“… Snow White.”
The queen said to the royal huntsman
“take Snow White into the forest and bring back her heart in this box.”
The huntsman took Snow White into the forest and told her to run away.
When night fell, the forest was a scary place to be all alone.
In the morning, Snow White followed some forest animals to a little cottage.
Seven dwarfs lived in the cottage.
When they came home, Snow White was asleep inside.
The magic mirror told the Queen where Snow White was staying.
The queen disguised herself as a lady selling ribbons.
She tricked Snow White. Snow White let the Queen lace her dress with a ribbon.
The Queen pulled it so tight that Snow White couldn’t breathe.
The dwarfs found Snow White on the floor.
They cut the ribbon and Snow White woke up.
Again the magic mirror told the Queen that Snow White was the fairest.
The Queen disguised herself as a lady selling combs.
She tricked Snow White.
“Now let me comb your hair,” said the Queen.
But the Queen used a poisoned comb.
She stuck it into Snow White’s scalp.
Snow White fell to the floor.
“Mirror, mirror on the wall,who is the fairest one of all?” asked the Queen.
“Snow White” said the mirror.
The dwarfs had saved her again.
The queen went to a secret place and made a poisoned apple.
She disguised herself as a peasant and tricked Snow White again.
Snow White bit into the apple and fell down as if dead.
This time the dwarfs could not rouse Snow White.
They made her a coffin out of gold and glass and inscribed it with the words:
“Here lies Snow White, the daughter of a king.”
A long time passed and Snow White lay in the coffin. She stayed beautiful and looked as if she was just sleeping.
One day a prince asked if he could take Snow White to his palace.
The dwarfs agreed reluctantly.
As the king's men carried Snow White away, they stumbled on some roots and the apple fell out of Snow White's mouth.


| To be done |
| -remove wine rack and build storage |
| -make bags to hang outside for storage by entry door |
| -change door hinges on cabins |
| -Plug holes in cabin doors, swap hinges and latch |
| -make two storage/seats for dining |
| -resew stitching on jib cover |
| -resew main cover and revise |
| -sew new window sun screen |
| -get new foam for aft cushions |
| -install stern seat |
| -install water maker |
| -clean, buff and wax hull |
| -refinish floors |
| -paint black between saloon windows white |
| -clean port fwd deck locker and paint |
| -fix all lockers on stern - repair locks, clean and paint |
| -seal top of rub rail |
| -hook up hoses in port head |
| -Reseal around all stantions, cleats |
| -clean starboard fwd deck locker and paint |
| -put rain shields on outside ports |
| -Replace hatch in v berth |
| -put on new name |
| -remove engine controls and clean and check for corrosion |
| -ref and ice box drain line or seal complete |
| -clean and paint port bilge |
| -clean port mid deck locker and paint |
| -remove wheel console and check and clean up all wires |
| -repair spots in port bilge |
| -lube through hulls |
| -grind port bilge spots for later repair |
| -put in new clear screen (isinglass, plexiglass??) |
| -install new solar panels |
| -alum plate on refrigerator and fan? on ice box side |
| -fix frig closing system / replace seals on fridge freezer |
| -clean and paint speaker covers |
| -repair/replace holding tank gauges |
| -replace lights in main cabin |
| -go through and order a list of spares |
| -Purchase and install TV/monitor |
| -Install Bitstorm wifi |
| -install new helm seat |
| -install cases for batteries |
| -install new batteries |
| -Purchase and install new stereo |
| -install autohelm compass |
| -add 2 new vents to fridge freezer 3 3/4 hole opening |
| -remove old generator wiring??? |
| -new light for over kitchen stove |
| -measure steering cables and order spares |
| -drill drain in rudder shelves |
| -rewire electrical in port bilge |
| -install bath cabinet, put in plugs and finish |
| -get spare water jugs |
| -get spare diesel jug |
| -install new clock and barometer |
| -new bulbs or lights for main cabin |
| -remove steering cable, inspect and ??? |
| -put lower mirror for Derek |
| -revise light so Derek can turn on in starboard head |
| -measure size of hold for storage measurement in Derek's berth |
| -de-corrode all electrical fittings |
| -install louvers on outside of main windows |
| -lubricate masthead sheaves with Teflon grease |
| -Find out about Wifi and vpn for boat |
| To buy at cheapest price |
| 7" x 8" mrror for Dereks bath |
| 1 diesel jug |
| racks with plastic baskets and curtain rod to hold for frig |
| Bitstorm Wifi stuff |
| 2 water jugs |
| new vents for fridge freezer that are 3 3/4 inch hole or cold plate |
| new light for over stove 18" max length |
| 22.5" by 10.25 " rain shield - 2 |
| stereo mp3 player |
| 17.25" by 10.25" rain shield - 6 |
| slider for helm seat |
| new helm seat |
| window shades for outside |
| 2 trojan t105 batteries |
| dining storage seats |
| name for boat |
| TV 22" wide for 3" thick. Max 21" tall |
| strataglass for bimini |
| 135 watt kyocera solar panels (northern arizona and wind $360 each) (energy bay including shipping $773) |
| aft cushion foam |
| bookshelf made |
| lights for interior |
| replacement hatch for Bowmar hatch 9401503 which is 20" by 20" opening size |
| Other electrical monitoring stuff |
| stern swing seat |
| Echo tec watermaker |
| pen/pencil/divider holder for top of chart table |
| Plastic bins for V berth that are 15 3/4 x 23" for front or 2' x 3' for top opening |
| battery cases |
| 50' of 1 1/2 inch sanitation hose |
| more sampson XLS 1/2 inch white with green and red flek |
| 12" x 11 7/8 inch cutting board for galley with finger hole in it |
| bilge paint - white |


{% extends 'base.html' %} {% block content %}
Sort by: ID Title Year Director Top Comments
Director: {{ movie.director }},
Comments count: {{ movie.commentitem_set.count }}


#include <MainScene.h>
Public Member Functions | |
| void | createNewWindow () |
| virtual const char * | getId () |
| MainScene () | |
| virtual void | onInitialize (bool firstRun) |
| virtual void | onShutDown () |
| virtual void | renderBackground (DrawingContext &context) |
| virtual void | update () |
| virtual | ~MainScene () |
Static Public Attributes | |
| const char * | ID |
Private Attributes | |
| Image * | danielImage |
| Font * | font |
| Image * | testImage |
Static Private Attributes | |
| const int | NEW_EVENT |
| const int | QUIT_EVENT |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 20 of file MainScene.h. |
|
|
Definition at line 22 of file MainScene.h. |
|
|
Definition at line 26 of file MainScene.h. |
|
|
Definition at line 17 of file MainScene.h. |
|
|
Definition at line 18 of file MainScene.h. |
|
|
Definition at line 21 of file MainScene.h. |


I have uploaded my RoR projects that I have created while I am working my way through Hartl’s Ruby on Rails tutorial.
Check out my Github page to see what I’ve done: Ruby on Rails Projects


WITNESS LIST
Health & Human Services
December 8, 2020 9:30 AM
COVID-19
ON:
Borel, Dennis Executive Director (also providing written testimony) (Coalition of Texans
with Disabilities), Austin, TX
Carter, Kia Medical Director of Child and Adolescent Psychiatry (also providing written
testimony) (Cook Children's Hospital), Fort Worth, TX
Crockett, Sarah Senior Public Policy Associate (also providing written testimony) (Texas
CASA), Austin, TX
Denton, Douglas Executive Director (Homeward Bound, Inc.), Dallas, TX
Ducayet, Patricia State Long-Term Care Ombudsman (also providing written testimony)
(Texas Health and Human Services Commission), Austin, TX
Fredriksen, Amanda Associate State director, Advocacy and Outreach (also providing
written testimony) (AARP), Austin, TX
Gloria, Terry Chief Executive Officer (also providing written testimony) (Texas Council
on Family Violence), Austin, TX
Kaplan, Seth President (also providing written testimony) (Texas Pediatric Society),
Frisco, TX
Keller, Andy President and CEO (also providing written testimony) (Meadows Mental
Health Policy Institute), Dallas, TX
Patt, Dr. Debra Chair, Council on Legislation, TMA (also providing written testimony)
(Texas Medical Association), Austin, TX
Registering, but not testifying:
ON:
Carlton, Stephen Executive Director (Texas Medical Board), Austin, TX
Ford, Victoria Chief Policy and Regulatory Officer (Texas Health and Human Services
Commission), Austin, TX
Gaines, Sonja Associate Commissioner (Texas Health and Human Services Commission),
Austin, TX
Kostroun, David Deputy Executive Commissioner for Regulatory Services Division (Texas
Health and Human Services Commission), Austin, TX
Schalchlin, Scott Deputy Associate Commissioner - SSLC Division (Texas Health and
Human Services Commission), Austin, TX
Taccetta, Kaysie Deputy Associate Commissioner for Child Protective Services (Texas
Department of Family and Protective Services), Austin, TX


Nursing students protest colleague's death in Anambra
by https://www.facebook.com/CheerfulpraiseEmma Elekwa, Onitsha
Students of School of Nursing, Iyienu Mission hospital, Ogidi in Idemili North local government area of Anambra state on Monday protested the death of one of their students, Emmanuel Aniagudo.
The deceased, a second-year male student, was reportedly crushed to death by a hit-and-run driver along the old Onitsha/Enugu last Friday.
Aniagudo was said to be crossing to the other side of the ever-busy road when he was suddenly knocked down by the speeding sienna car and thrown into the drainage system.

The protesting students, mostly in their nursing gowns, carried placards, barricading the major road and making bonfire with used tyres.
Some of the inscriptions on the placards read, “Enough of these killings”, “we need check-points”, there should be bumps inside the hospital premises and on the major road where the student nurse was hit”, hospital management should compensate the family.”
Representative of the National Association of Nigerian Students (NANS) in the institution, Edeh Emmanuel, who claimed to had witnessed the incident, regretted that the deceased could not survive despite efforts to revive him.
He said, “I saw it all when it happened. He was hit by the speeding sienna car and thrown into the gutter.
“Blood was all over his body and we used stretcher to bring him into the hospital for immediate medical attention.
“He was provided with oxygen but he gave up the ghost.”
Reacting, the Hospital Administrator, Rev. Tochukwu Okwuchukwu, described the incident as unfortunate, assuring immediate installation of speed bumps on the road leading to the school.
“I’ve appealed to the protesting students to calm down and to leave the major road into the hospital compound to avoid miscreants taking advantage of the opportunity to cause havoc.
“We will build the bumps along the hospital roads as they demanded. In fact, we are starting off immediately,” he added.


WITNESS LIST
Appropriations Committee
November 8, 2017 - 9:00 AM
(SUBCOMMITTEE MEETING - Disaster Impact and Recovery)
Hurricane Harvey Funding Relief and Recovery Efforts
On:
Armstrong, Jennifer (Texas Windstorm Insurance Association)
Bujan, Charles (City of Port Aransas (Mayor))
Bush, George (Texas General Land Office)
Canales, Barbara (Port of Corpus Christi)
Casterline, Leslie (Aransas County (Commissioner))
Dickey, Robert (University of Texas - Marine Science Institute)
Doss, Justin (Christus SPOHN Health System)
Durden, David (Texas Windstorm Insurance Association)
Fraire, Jacob (Texas Association of Community Colleges)
Gonzales, Melissa (Refugio Independent School District (Superintendent))
Head, Stephen (Lone Star College and Texas Association of Community Colleges)
Kendrick, Jimmy (Fulton, Texas (Mayor))
Lopez, Joe (Taft Independent School District (Superintendent))
Lowery, Petrina (DeTar Healthcare System)
McComb, Joe (City of Corpus Christi (Mayor))
McCrohan, Betty (Wharton County Junior College)
Morath, Mike (Texas Education Agency)
Neal, Loyd (Nueces County (Judge))
Quinn, Donna (Driscoll Children's Hospital)
Schuss, Brian (Flour Bluff Independent School District (Superintendent))
Simpson, Terry (San Patricio County (County Judge))
Strawbridge, Sean (Port of Corpus Christi Authority)
1


Meetup
Description
Location
Members
Created
Cost
Next Event
Tags
Organizers
APPLY
Location:
At least: 1
100 Members
$
$$
$$$
FILTER
Empty Cart.
Go add groups!!
FACEOFF
VIEW GROUP
VIEW GROUP
VIEW GROUP
Profile
Username: Momo
Password: ••••••••
Email<EMAIL_ADDRESS>Interests: Hiking, Art & Culture


Agent of ex-Liverpool forward Duncan banned and fined for social media posts
Saif Rubie made headlines earlier this year, accusing the club of blocking his client’s transfer.
by The42 TeamSAIF RUBIE, THE agent of former Liverpool forward Bobby Duncan, has been banned by the Football Association (FA) from acting as an intermediary for six weeks and fined £10,000 (€11,800) for messages posted on Twitter.
Duncan completed a permanent move to Fiorentina on 2 September following a turbulent few days that saw Rubie take to social media to accuse Liverpool of attempting to block a transfer.
Rubie singled out Reds sporting director Michael Edwards for criticism and alleged the treatment of the 18-year-old – who is Steven Gerrard’s cousin – showed “zero consideration” for the player’s mental health.
Liverpool described the allegations as “inaccurate” and “inflammatory”, while club legend Jamie Carragher and supporters rounded on Rubie, who later deleted his Twitter account.
The FA has now taken action against the agent by suspending him from 4 December until 15 January, handing him a hefty fine and sending him on an Educational Programme for improper use of social media.
Rubie has been accused on bringing the game into disrepute with his social media messages, although the FA has not specified which posts the punishment is for.


Hazardous Alteration
{^g}Skill Modifier{^n}{^w}The mutagen's effects last for much longer, however it doesn't come without drawbacks to the user.
${value} Second Duration
65
${value}% Energy Leech Resistance
-20
${value}% Fire Resistance
-20
${value}% Vitality Damage Resistance
-20
MaxLevel
1
UltimateLevel
1


You are reading the manual for Willow, a Python framework for experimental economics developed at the Center for the Study of Neuroeconomics at George Mason University. This manual presumes that you already have an understanding of experimental economics, of HTML, and of Python programming.
If you are interested in learning about experimental economics, you could do worse than to have a look at the following textbooks:
Daniel Friedman, Experimental Methods: A Primer for Economists
John Kagel and Alvin Roth, The Handbook of Experimental Economics
In order to get started with Python if you already know how to program in some other language, you can try
Mark Pilgrim, Dive into Python http://diveintopython.org
Guido van Rossum et al., The Python Tutorial http://docs.python.org/tutorial/
If you want to learn both the craft of computer programming and the Python programming language at the same time, you are in luck, since Python is an excellent first language. Some free resources include:
Jeffrey Elkner, Allen B. Downey, and Chris Meyers, How to Think Like a Computer Scientist http://openbookproject.net/thinkCSpy/
Swaroop C. H., A Byte of Python http://www.swaroopch.com/notes/Python
Also, in order to use Willow, you need to have basic knowledge of HTML and CSS, the languages used to build web pages. For this I strongly recommend
Kennedy and Musciano, HTML & XHTML, The Definitive Guide, O’Reilly.
O’Reilly books are available full-text through an online service called Safari, which many universities subscribe to. In particular, if you are at GMU, you can get Safari at http://proquest.safaribooksonline.com.mutex.gmu.edu/?uicode=viva and you can this book at http://proquest.safaribooksonline.com.mutex.gmu.edu/0596527322 . If you are at some other institution, try your library web site listing of online databases.
Willow is a tool for making the kinds of computer user interfaces typically used in experimental economics. Without Willow, you might design such an interface from scratch, or by modifying earlier from-scratch software written for similar experiments. Using Willow, you can do the same thing, but faster and better.
Willow sets out to accomplish this goal not by providing canned routines for commonly performed experiments. After all, it is precisely because our experiments are different from what has gone before that we bother with them. Rather, Willow is a generic toolkit that makes a lot of the things we do in experimental economics easy.
To use a Willow program, you need only install your program on a single "monitor" computer. The computers used by your research subjects will simply run a web browser, which connects to a web server that runs on the monitor computer. The user interface for the subjects will be displayed inside the browser window.
Willow is a versatile program, and you can use it for many different interfaces; but you might just be curious what a Willow interface can look like. Here are some examples taken from the first study that used Willow at the Center for the Study of Neuroeconomics and the Interdisciplinary Center for Economic Science at George Mason University.
In this manual, I will use fixed-width font to indicate anything that is literally part of some HTML, CSS or Python code. For longer snippets of code, I will use boxes, like so:
import random print random.random()
Note that there are colors in these boxes, which are merely a typesetting convention to make it easier to read the code. Similarly, you may find that many of the better programmer’s text editors will color your code in a similar (but not identical) way. Again, the colors are not part of the code, and they are not actually stored in your code files, as you can easily verify by opening them up in a less fancy text editor.
Willow relies on HTML, the hypertext markup language, for the purpose of constructing a user interface.
An HTML document is a text file with some special markup sequences. To practice with HTML, you can construct HTML documents with a text editor, and load them in a web browser.
Consider this example:

This is a paragraph, with a bold bit in it, and a
line break and a link.

This is the first item of an ordered list.

This is the second item of an ordered list.

This is the first item of an unordered list.

This is the second item of an unordered list.

This is a div. It has a span in it.

This is a div. It has another span in it.

If we type this into a file called example.html and load that file in a web browser, this is what we see:
Even though this is a simple example, it already illustrates some of the most important points about HTML:
HTML is made up of elements, which are delimited by tags. For instance, the above example starts with a p element, the start of which is marked with an opening tag
, and the end of which is marked with a closing tag
.
Elements can have contents. For example, the b element in the above example contains the text bold.
Some elements, such as br, do not have contents, and those do not need a closing tag. (Sometimes, you will see these written like
; this is an XML thing, which you can read about elsewhere.)
Elements also can have attributes. In the above example, the a element has an href attribute, with value http://google.com.
In HTML, any sequence of newline characters and/or blank characters is always treated as a single blank. Extra blanks, or newlines, in the HTML source have no effect. If you do want a line break, you can use the the HTML element
.
Most HTML elements have standard meanings for the browser. The b element is rendered by typesetting its contents in bold, the a element describes a link, etc. Strictly speaking, many of these meanings are not part of the HTML standard, but in practice, they are pretty consistent across browsers. There are two exceptions to the rule that each HTML element has a standard meaning: div and span. These have no inherent meaning, and only become useful when we start using things like CSS. The difference between div and span is that a div is typeset above/below whatever comes before/after it, while a span is typeset in-line.
Next, we will see a list of common HTML elements.
A paragraph.
An unordered (bulleted) list.
An ordered (numbered) list.
An item for a list.
A generic chunk of text displayed vertically.
An input widget
A piece of text in bold
A piece of text in italics
A generic chunk of text displayed in-line.
A link
A line break
A horizontal line
A table
A table row
A table element
The last three of these fit together like so:

Column 1, Row 1	Column 2, Row 1

Column 1, Row 2	Column 2, Row 2

Some of the more common HTML attributes:
A table with 1 pixel borders.
A link to http://google.com/
A button with label foo
A text field.
You can learn more about HTML by using either Firefox with the Firebug plugin, or Google Chrome. Right-click anywhere on the page and select "Inspect element." This pulls up an HTML explorer system, which looks like this in Google Chrome (Firefox with the Firebug plugin is similar):
By playing around with this feature of your browser, you can learn a lot of about HTML and CSS.
TBA
You should already know Python before reading this manual, but there are few Python features that you may not be familiar with even if you do have experience with Python and that will come in useful for Willow.
Python has a convenient way of putting together strings with the % operator.
print "foo %s baz" % ("bar",) print "foo %s baz %%" % ("bar",) print "foo %s baz %s" % ("bar", "quux") print "foo %s baz %s" % ("bar", 42) print "foo %s baz" % "bar"
If you run that through Python, you will see
foo bar baz foo bar baz % foo bar baz quux foo bar baz 42 foo bar baz
As you can see, the % operator takes a string, called the "format string", on its left hand side, and a tuple on its right hand side. For every "gap" in the format string, indicated by %s, the corresponding element from the tuple will be substituted.
In fact, there are a number of gap markers other than %s (such as %d, %r, etc.) which are described in the "String Formatting Operations" section in the "Built-in Types" chapter of the Python library documentation. In practice, %s is nearly always what you want. If you happen to actually want a percent sign in your string, you should use %%.
Also, if you only have one value to substitute, you don’t need to put it in a one-element tuple; the % operator is nice enough to accept interpret non-tuple values as though they were one-element tuples.
To install Willow, you extract the zip file to a convenient location. You will do this anew for each of your Willow projects. In addition, you will need to have Python installed. Willow has been tested using Python 2.6 on Ubuntu GNU/Linux. You should be able to use it with Python 2.6 on Windows and Mac OSX as well. If you do not have Python 2.6 on your computer, get it from http://www.python.org/download/releases/2.6.3/ and then come back. If you are not sure whether you have Python 2.6 on your computer, just move on to the next section of the manual. If things don’t work, you’ll notice soon enough, and you can go back and install Python. Do not use Python version 3. It will not work.
While programming, you will want to run Willow from within a programmer’s text editor (or, if you care for such things, an Integrated Development Environment). On Mac and Linux, you can use the IDLE editor that ships with Python. If you are running Windows, the version of IDLE that ships with Python on that platform is very buggy, and I recommend strongly that you get a different text editor: in particular, I recommend SciTE, which is a very simple drop-in replacement for IDLE. On Mac or Linux, you can get away with just using IDLE, although you may find that SciTE is a little more polished. Either way, SciTE can be had from http://www.scintilla.org/SciTE.html .
In the Willow folder, you will find a file named lesson.01. You need to run this file: double click on it, or run the command python lesson01.py from the command line. Once the lesson01.py program is running, fire up a web browser and point it to http://localhost:8000/. You should see a page that looks like so:
Now pull up the lesson01.py file in IDLE or SciTE.
In IDLE, this looks like so:
In Scite, it looks like:
See here the code of a very simple but working Willow program. You can run it using the Run > Run Module menu option in IDLE or the Tools > Go menu in SciTE, or by pressing F5 (that shortcut key is the same in both SciTE and IDLE).
Again, you now need to point a web browser to http://localhost:8000.
If you see an error message like "address already in use," you are probably trying to run two instances of Willow simultaneously. You should stop the first one first (just close the window).
Now, let us look at the above code. Most of it is boilerplate, but the good news is that this is all the boilerplate you need. The first line imports the willow library. It assumes that willow.py is in a subdirectory willow of the directory in which lesson01.py is; this is how things are set up for the sample programs, and if you put your own programs in the same place, it will just work. The next two lines define a session function, and the last line instructs Willow to start the web server, using the session function that has just been defined.
Together, these four lines define a web server that you can connect to from a browser. If the browser is running on the same machine as the server, you can use http://localhost:8000 as a URL. If it is running somewhere else, you must find out the IP address of the server. (If you don’t know it, there is a whole chapter further down in the manual about how to figure it out.) If the IP address is, say, <IP_ADDRESS>, then you can reach your Willow server using http://<IP_ADDRESS>:8000. The :8000 part is called the port number; you can specify a different port number as an extra argument to run (e.g. run(session, 8001)) if you insist on a port different from 8000.
Once the web server is running, for each client that connects to it, the session function will be called once. It will keep running until it returns. We say that each session function runs in its own "session thread". This means that several "copies" of the session function are running simultaneously, one for each client.
In this case, we want to simply display the text "Hello world." in the web browser of every client that connects, so we have a very simple session function that does nothing but add("
Hello, world.
"). The add() function adds an HTML snippet to the web page being displayed in the client’s browser.
Try connecting to localhost:8000 in multiple browser tabs. You’ll see that each one shows "Hello, world." This is because the session() function gets called once for each client that connects.
In real applications, we usually do not want to do the same for every client that connects. More likely, we’ll want one client to show some sort of experimenter console, one client to show the interface for subject 1, one client the interface for subject 2, etc.
Have a look at lesson02.py:
from willow.willow import * def session(me): if me == 0: add("Hello monitor %s" % me) else: add("Hello subject %s" % me) run(session)
| The % operator in Python is very useful for constructing strings. You can read about it in section 6.6.2, "String Formatting Operations", of the Python 2.6.4 Standard Library reference manual. |
As you can see, there is still only one session() function, and for each client that connects, a session thread is started that runs the session() function. Each client runs the exact same function, but… the session function takes an argument, which we call me, and for each client, it gets called with a different value for me: 0, 1, 2, and so on. If you reload the page a bunch of times, it looks like this:
In this lesson, we will see some of the Willow functions for manipulating user interface elements. All of these are based on HTML and CSS, and it is crucial that you acquire a basic understanding of these languages. An extensive description of HTML and CSS is outside the scope of this manual.
Have a look at lesson03.py.
from willow.willow import * def session(me): add("") add("
The division of " "labor is limited " "by the extent of the " "market.") add(" and subdivision", "#a") let("labour", ".b") poke("href", "http://ebay.com", "a") pop("important","#a") push("important",".b") add("
Microfoundations.
") add("
Prices.
") hide(".elusive") show(".hidden") run(session)
This displays a web page like so:
This shows off all of Willow’s UI manipulation functions. Let’s go through it line by line.
add("")
First we add a style sheet to the page. Again, CSS is beyond the scope of this manual and you should go out and read up on it, but what this comes down to is that we instruct the browser to typeset in bold all HTML elements that have class "important" turned on.
add("
The division of " "labor is limited " "by the extent of the " "market.")
Note that in Python string literal juxtaposition adds the string literals together, which makes for a convenient way of splitting long strings over several lines.
The  element in HTML has no default meaning, and without any style sheets or other manipulations, a piece of HTML enclosed in a  is exactly identical to the same piece of HTML not so enclosed. In the above fragment, we have two  elementss. Note that because the style sheet instructed the browser to print all elements of class important in bold, the word "division" is printed in bold; or at least, it would be, if we did not manipulate it further.
add(" and subdivision", "#a")
This shows that you can add text not just to the page as a whole, but also to particular elements. The optional second argument to add is a CSS selector. The most common CSS selectors are:
p, which refers to all
 elements;
h1, which refers to all
 elements;
etc.;
.x, which refers to all elements with class=x;
#a, which refers to the first element with id=a.
Note that some selectors can refer to more than one element, and in that case, your HTML snippet gets added to all matching elements.
In this case, what we are asking Willow to do is to find the first HTML element with id=a and add the text " and subdivision" to the end of it it.
set("labour", ".b")
The set() function is just like the add() function except that instead of adding HTML to the end of some element, it replaces the entire contents of the element. In particular, set("") clears the entire page!
poke("href", "http://ebay.com", "a")
So far, we have seen the functions add and set that manipulate the contents of HTML elements. But HTML elements have attributes as well as contents. For instance, if you write …, you have created an  element with contents "…" and with an href attribute with value foo. The poke() function serves to manipulate attributes. In this case, we set the href attribute of every single  element on the page to be http://ebay.com.
pop("important","#a") push("important",".b")
In HTML, a single element can have more than one class. You can write that as
…
. The pop() and push() functions are there to remove a class from an element and to add a class to an element, respectively, without changing any other classes that the element might have.
add("
Microfoundations.
") add("
Prices.
") hide(".elusive") show(".hidden")
The hide() and show() functions do just that: hide and show elements. Willow is set up so that any element with class hidden set is hidden by default and only shows up when you call show() on it.
So far, we have seen the Willow UI primitives: add, set, poke, push, pop, hide, and show. In combination with HTML and CSS, these primitives make a very powerful UI language.
Now that we have seen how to produce output on the client screens, you may be wondering how we can read input. But before we get to that, we will first discuss another important feature of Willow: its communication system.
Consider lesson04.py.
from willow.willow import * def session(me): if me == 0: add("
Monitor
") while True: msg = take({"tag": "HELLO"}) add("
Client %s logged in" % msg["number"]) else: add(me) put({"tag": "HELLO", "number": me}) run(session)
In this short program, we can see a typical use case for the important Willow functions put() and take(). The first client, for which me==0, acts as a control panel that displays information about other clients coming online. In order to convey that information, each client other than the first puts a dictionary {"tag":"HELLO", "number":me} on the Board. The first client retrieves these dictionaries and uses them to display information about logins.
After the monitor client and 3 other clients have connected, the monitor client display would look like this:
To fully understand this, we must understand the Board. The Board is the one and only data structure that is shared between the various session threads in Willow.
The board contains dictionaries. Dictionaries are sets of key-value pairs. To put my_dictionary on the board, you call put(my_dictionary). For instance, to put the empty dictionary {} on the board, you call put({}), or to put the very abridged Dutch-to-English dictionary {"rood":"red","nederlands":"dutch"} on the board, you call put({"rood":"red","nederlands":"dutch"}).
To retrieve my_dictionary from the board, you call take(my_dictionary). In practice, though, you typically don’t know yet what dictionary you want to retrieve. For that reason, take() allows you to leave out keys you aren’t sure of. In the extreme case, you leave out all keys and call take({}), which means "please retrieve any dictionary whatsoever from the board."
The take() function is blocking. This means that if there is no matching dictionary on the board, it will sit around waiting until one appears. This is what happens in the example code: the first thread (the one with me==0) sits around waiting for dictionaries of the form {"tag":"HELLO", …} to show up on the board. Every time one such dictionary shows up, the take() function returns it, the loop loops, and the take() function is called again, blocking until the next dictionary shows up.
When a dictionary is gotten with take(), it is removed from the board. Therefore, in the above code, you do not need to worry about looping around retrieving the same dictionary over and over again. If you want to retrieve a dictionary and leave it available (maybe for some other thread), you simply put it back on with put().
Another important trick in the use of take() is that you can specify more than one pattern. For instance, take({"tag":"HELLO"}, {"tag":"ERROR"}) blocks until either a dictionary with the key-value pair "tag":"HELLO" or a dictionary with the key-value pair "tag":"ERROR" shows up. take({"tag":"HELLO"}, {"foo":3}) blocks until either a dictionary with the key-value pair "tag":"HELLO" or a dictionary with the key-value pair "foo":3 shows up. And so on.
Finally, I will mention grab(). It is like take(), except that it does not block. If a matching dictionary is available, it will return that, but if there is none, it will simply return None (unlike take(), which will sit there twiddling its thumbs until a matching dictionary shows up).
| You could, conceivably, have your own shared data structures simply by declaring some global variables outside of session(), but I recommend that you don’t. In order to make sure your data structures remain consistent, you would have to implement rules to make sure that no two threads fiddle with them at the same time ("mutual exclusion"), which can rapidly become extremely complicated. The Board is a variant on a data structure known as a Tuple Space, which already has mutual exclusion built into it. |
Now that we have seen how to manipulate what appears on a client screen, we will turn our attention to the issue of input.
There are two basic ways of giving input to a Willow client: you can click things, and you can fill out text fields.
The lesson05.py code demonstrates both.
from willow.willow import * def session(me): add("
Please enter your name.") add("<input id='name' type='text'>") add("<input id='go' type='submit'>") take({"tag": "click", "id": "go", "client": me}) name = peek("#name") add("
Hello, %s." % name) run(session)
This should initially display a screen that looks like so:
You can then type something in the text box and click the button labeled "Submit", and the screen will look like:
What’s going on here?
First of all, HTML elements that look like
<input type='submit' ...>
are buttons.
In HTML, each <input> element that is a button must have two attributes: type must be set to submit, to make sure we are displaying a button and not some other sort of input element, and value must be set to the text that is to be on the button (or, if it is left out, the text defaults to "Submit", or possibly something else if your browser is set up for a language other than English).
In Willow, your button must additionally have an id attribute, which is how we keep track of which buttons get clicked.
When a button gets clicked, a dictionary
{"tag": "click", "id":_id_, "client":_n_, "time":_t_}
is automatically posted onto the board, where
n is the number of the client that received the button click;
id is the id of the button;
t is the time in milliseconds since Jan 1, 1970 0:00 UTC, as measured by the client, when the button was clicked
This is why, after we have displayed the button, we can just call take({"tag":"click", "id": "go", "client": me}), which will block until the button is clicked. Note that if you insist on blocking one client thread until a button in some other client thread has been clicked, you can do that, simply by replacing me in the above call to take() by some other integer (but it is not recommended).
| If the button is clicked multiple times, multiple dictionaries will be inserted. This may result in behavior you may not necessarily intend. If you want to wait for a button to get clicked that may have been clicked before you started waiting, you will need to clear those old dictionaries off the board using grab(). |
To show a text field, we use a piece of HTML that looks like
<input id='name_of_text_field' type='text'>
and then we call peek("#name_of_text_field"), which returns the current content of that text field. You can also use peek() for checkboxes, radioboxes, <textarea> elements, and most other input-type elements that you can read about in HTML books. In the above case, we only start looking for what’s in the field after the user has pressed the button.
Many of the Willow functions, even though by default they operate on the client display associated with the current session thread, can also operate on a different client display if you pass the client=n optional parameter. This is never necessary, but it may be more convenient than passing messages through the board to the other session thread so that it can then manipulate its corresponding client display.
Take for instance the code in lesson 4:
from willow.willow import * def session(me): if me == 0: add("
Monitor
") while True: msg = take({"tag": "HELLO"}) add("
Client %s logged in" % msg["number"]) else: add(me) put({"tag": "HELLO", "number": me}) run(session)
We could rewrite that as follows:
from willow.willow import * def session(me): if me == 0: add("
Monitor
") else: add("
Client %s logged in" % me, clients=0) add(me) run(session)
| Strictly speaking, the above programs are not entirely equivalent. If the first session thread executed very, very slowly and the second client connect immediately after the first, then the "Client 1 logged in" message could conceivably show up before the "Monitor" heading when running the second program, but not when running the first. |
Look at this:
from willow.willow import * def session(me): add("Hello, ") def ping(): put({"tag":"PING", "client": me}) background(ping, 3) take({"tag":"PING", "client": me}) add("world.") run(session)
It shows "Hello, " on the screen, and 2.3 seconds later, it adds " world."
That’s all there is to this one. Use the background(f,dt) function to call the function f in the background, after a delay in seconds of dt. Note that you can also use this (typically with dt=0) for any other background tasks, like dealing with a chatbox while the main task deals with the rest of the experiment.
from willow.willow import * def session(me): add("Hello, world.") log("hello", "world", me) run(session)
This is how you cause your Willow program to produce a data file.
In this case, a data file was produced in the log subdirectory (i.e. folder) called 2010-02-23-22-00-05.csv. The name is chosen automatically based on the date and time (year-month-day-hour-minute-second).
The file contains:
1266985186.84,hello,world,0<PHONE_NUMBER>.28,hello,world,1<PHONE_NUMBER>.55,hello,world,2<PHONE_NUMBER>.76,hello,world,3
This is a CSV file, which is a simple text-file based spreadsheet format. It is understood by Excel, OpenOffice, Stata, and other data analysis software. You can also just open it in a text editor.
Each row will automatically get a timestamp added to the front of it, which is a large integer representing the number of seconds that have passed since the "Unix epoch" on January 1, 1970, 0:00 UTC. This may seem like an odd choice of timestamp format, but the advantage of this type of timestamp is that it makes sense to subtract them!
from willow.willow import * def session(me): if me == 0: add(open("lesson09_0.html")) msg = take({"tag": "click"}) bid = int(msg["id"]) put({"tag": "bid", "amount": bid}) show("#wait") add(bid, "#offer") msg = take({"tag": "accept"}) accept = msg["accepted"] if accept: show("#accept,#pay") add(10 - bid, "#payoff") else: show("#reject,#pay") add(0, "#payoff") log("bid", bid) log("reaction", accept) elif me == 1: add(open("lesson09_1.html")) msg = take({"tag":"bid"}) bid = msg["amount"] show("#offer") add(bid, "#bid") msg = take({"tag": "click"}) accept = msg["id"] if accept == "accept": show("#pay") add(bid,"#payoff") put({"tag": "accept", "accepted": True}) else: show("#pay") add(0, "#payoff") put({"tag": "accept", "accepted": False}) else: add("
Experiment is full.
") run(session)

Pick an offer

 <input class="choice" id='0' value='$0' type='submit' /> <input class="choice" id='1' value='$1' type='submit' /> <input class="choice" id='2' value='$2' type='submit' /> <input class="choice" id='3' value='$3' type='submit' /> <input class="choice" id='4' value='$4' type='submit' /> <input class="choice" id='5' value='$5' type='submit' /> <input class="choice" id='6' value='$6' type='submit' /> <input class="choice" id='7' value='$7' type='submit' /> <input class="choice" id='8' value='$8' type='submit' /> <input class="choice" id='9' value='$9' type='submit' /> <input class="choice" id='10' value='$10' type='submit' />

You offered $...

Player 2 accepted your offer!

Player 2 rejected your offer!

You earned $...

Waiting for player 1...

 Player 1 offered $... <input class="choice" id='accept' value='accept' type='submit' /> <input class="choice" id='reject' value='reject' type='submit' />

You earned $...

Most of the time, you are going to want input from the mouse or the keyboard. Web browsers know how to talk to mice and keyboards, which makes it easy for Willow to get the input to you. Occasionally, you may have a need for more exotic input devices.
For instance, at GMU we use a device called the "Lumina Response Pad for MRI", manufactured by a company called Cedrus, which is a set of two boxes with two buttons each that you can hand to a subject inside an MRI machine. These boxes are hooked up to something called the "LSC-400 controller," which in turn hooks up to a PC using a serial (RS232) cable.
If you have an LSC-400, or any other device that talks to your PC using a serial cable, you may want to have a look at the file named willow/bb.py. This is a little stand-alone application that will read from a serial port and post each byte that comes in on that serial port onto the board.
To get this to work, start bb.py in a separate terminal, like so:
$ python bb.py
You can pass three optional arguments to bb.py, like so
$ python bb.py -p 2 -h localhost:8888 -t mytag
The first argument is the port number of the serial port (default 0), the second is the host and port number where willow is running (default "localhost:8000") and the third is the tag to use when bb.py posts things to the board… but here we’re getting ahead of ourselves, so let’s first have a look at some bb.py output.
Suppose we start bb.py and we push a button on our input device that causes some input to be sent in on the serial cable and we see this:
Reading data from port : 0 Posting data to host : localhost:8000 Using tag : serial Received : 3 ERROR - no willow on : localhost:8000
This means that bb.py accurately received a byte from the serial port, to wit "3", but it could not forward it to Willow, because it did not find an instance of Willow running on localhost:8000. Let’s start a Willow program that knows how to take serial input, in a separate window:
python lesson10.py
The code for this is simple:
from willow.willow import * def session(me): while True: msg = take({"tag": "serial"}) add("
%s" % msg["byte"]) run(session)
Now, we push some more buttons, and we see in the window where bb.py is running:
Reading data from port : 0 Posting data to host : localhost:8000 Using tag : serial Received : 3 ERROR - no willow on : localhost:8000 Received : 3 Posted : { "tag": "serial", "byte": "3" } Received : 3 Posted : { "tag": "serial", "byte": "3" } Received : 4 Posted : { "tag": "serial", "byte": "4" }
If we load a web browser and point it to localhost:8000, we now see input coming in from the serial device!
(If you happen to have an LSC-400, by the way, you’ll want to set the "mode" to "ASCII/MEDx" and the "speed" to "9600 baud". If you have some other input device, you may want to play around with Hyperterm on Windows or Cutecom on Linux to see how it works. If you can get it to work with Hyperterm or Cutecom but not with bb.py, you should read the documentation for the pyserial library and use that to hack on bb.py. Let me know!)
The selector argument can take any CSS selector. The CSS selector mini-language is rather rich, but the most typical cases are things like p (to get at all
 elements), #a, (to get at the first element with id="a"), and .a (to get at all elements with class="a"). For more information, consult any book or web page on CSS. Whenever selector is omitted, the selector "body" is implied, which means you are referring to the entire body of the HTML document. Aside from CSS selectors, jQuery extensions are also allowed. The most useful is of the form selector:eq(n), which selects the n-th element that matches selector.
By specifying an integer, or a sequence of integers, for clients, you can operate directly on clients other than the one associated by default with the current session thread.
Whenever timestamp=True, you are requesting a tuple to be posted of the form {"tag":"timestamp","client":n,"time":t} that gives you a millisecond timestamp of when the action was executed by the client.
Whenever you specify the delay=dt option, the execution of that action is delayed by dt seconds (you can specify fractions of seconds, too). This is done on the client side with millisecond accuracy.
If you have lots of closely spaced delayed events, at some point the browser may start lagging; but in Google Chrome, I have gotten it up to a set() event every milisecond with only a very slight lag.
Set the content of the HTML element(s) referred to by selector on to be content. Whenever content is a file descriptor that can be read from, the contents of the file are automatically substituted.
Add content to the content of the HTML element(s) referred to by selector. Whenever content is a file descriptor that can be read from, the contents of the file are automatically substituted.
Change the value of attribute attribute to be value in HTML element(s) referred to by selector.
Returns the value of the HTML <input> or <textarea> element(s) referred to by selector.
Add the CSS style style to the HTML element(s) referred to by selector.
Remove the CSS style style from HTML element(s) referred to by selector.
Hide the HTML element(s) referred to by selector.
Show the HTML element(s) referred to by selector, if previously hidden.
Post the dictionary onto the communication board.
Block until a dictionary becomes present on the board that matches at least one of the queries, then remove and return it. A dictionary matches a query if it contains all the key-value pairs in the query (plus, optionally, some others).
If a dictionary is present on the board that matches at least one of the queries remove and return it; otherwise return None. A dictionary matches a query if it contains all the key-value pairs in the query (plus, optionally, some others).
This starts the Willow web server on the specified port (or port 8000 if you leave the second argument out). The web server will create a thread for each client that connects, and each thread will run the session function, passing as an argument the client ID.
Client IDs will be assigned sequentially, unless the URL is of the form http://whatever-host/n, where n is an integer, and n is not taken yet, in which case the client ID will be n.
If a client ID is requested that already exists, an attempt will be made to replay all messages previously sent to that client. This provides a limited amount of recovery from browser crashes. If the browser crashed while a peek or timestamp request was pending, this may not be sufficient. An attempt to fix that is in the works.
The web server will search for requested files in the current directory, among other places, so you can for instance include images in your pages.
Run the function fn in the background (as a separate thread), with an initial delay specified in seconds. Fractions of seconds are allowed.
Wait for delay seconds. Fractions of seconds are allowed.
Write (x,y,…) to the log file as a record, with the number of milliseconds since January 1, 1970 0:00 UTC prepended as the first column. A new log file is created in the log folder whenever the Willow library is loaded, and it bears a name based on the date and time when it was created. For instance, if Willow was invoked at 15:32:42 on February 2 of the year 2010, the file would be called log/2010-02-10-15-32-42.csv. This particular date-and-time format is used so that the files can be sorted by date/time. The log files are in CSV format and can be opened with a text editor or a spreadsheet program.
Some Willow features are accessed by means of CSS classes:
Any element that has class hidden turned on will start out hidden. You can call show() on it to make it appear. Example:
At the moment, you cannot trade widgets.

Any element that has class bait turned on will automatically get the additional class mouse turned on whenever the mouse pointer is positioned over that element. This can be used to create "hover" effects.
When a button with (whether <input type="submit"> or <button></button>) or any element with class="clickable" is clicked, a dictionary like is inserted into the board automatically behind the scenes like so:
{"tag":"click", "id":_id_, "client":_n_, "time":_t_, "value":_val_}
where
n is the number of the client that received the button click;
id is the id of the button;
t is the time in milliseconds since Jan 1, 1970 0:00 UTC, as measured by the client, when the value was checked;
val is the contents of the text box
When the user presses a key, a dictionary like is inserted into the board automatically behind the scenes like so:
{"tag":"key", "client":_n_, "time":_t_, "value":_val_}
where
n is the number of the client that received the button click;
t is the time in milliseconds since Jan 1, 1970 0:00 UTC, as measured by the client, when the value was checked;
val is the key pressed
This is an extension library. It is liable to change, much faster than Willow itself, and not be be as well documented and tested. But I don’t want to withhold it either. This documentation is generated directly from the branch.py source file.
This function is a replacement for run(). If clients is not specified, it will display buttons on client 0 as clients 1, 2, … log on, which show subsets of the clients that have logged on so far. You can click one of these buttons at any time, and at that point, the function session() will be run once for each client IN THE SUBSET, with its client ID as the first number and the list of all client IDs IN THE SUBSET as its second argument. Clients that have connected but that are not in the subset will get a big X on their screens. The second way of using assemble() is to specify an explicit argument for clients=, some list of integers that indicates which clients you want. Once those client numbers have logged on, the session function is started once for every such client, and again any clients not in the set get a big X. === Examples ===
There is much additional useful code in the example_*.py files, which illustrate various ways to use Willow.
You need the IP address of your monitor computer in order for your client computers to connect to it. It would be convenient if Willow could display the right IP address for you to use, but unfortunately, this is easier said than done, since a computer can have multiple IP addresses at the same time: IP version 4 and IP version 6, on the wireless network, on the ethernet network, on the "loopback" network, and so on.
On Linux on my computer, I use the ifconfig command at the command line. When I enter
$ ifconfig
the computer responds
$ ifconfig eth1 Link encap:Ethernet HWaddr 00:23:ae:1e:9e:ac UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) Interrupt:17 eth2 Link encap:Ethernet HWaddr 00:24:2b:c6:a4:76 inet addr:<IP_ADDRESS> Bcast:<IP_ADDRESS> Mask:<IP_ADDRESS> inet6 addr: fe80::224:2bff:fec6:a476/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:10076 errors:0 dropped:0 overruns:0 frame:7868 TX packets:10906 errors:20 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1571308 (1.5 MB) TX bytes:1341157 (1.3 MB) Interrupt:17 Base address:0xc000 lo Link encap:Local Loopback inet addr:<IP_ADDRESS> Mask:<IP_ADDRESS> inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:85540 errors:0 dropped:0 overruns:0 frame:0 TX packets:85540 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:41237280 (41.2 MB) TX bytes:41237280 (41.2 MB) $
| In this and many other software manuals, $ is used to indicate the Linux/UNIX prompt. On your computer, it may be different. % is a popular choice, too, for example. |
There is much information here, but we only need a little. First, notice that this computer has three network interfaces, called eth1, eth2 and lo. lo is the loopback device; it does not correspond to any actual hardware, but it is rather a contraption that the operating system uses so that you can make connections to your own machine at address <IP_ADDRESS> even when the network is down. The other two network devices are actual network cards that are in the computer; as it happens, eth1 is a wired Ethernet network, and eth2 is a wireless 802.11g network. According to the information above, the computer has IP address <IP_ADDRESS> on eth2, and it has no IP address on eth1, which makes sense, because the wired connection was not plugged when I executed the command. In the output above you can also see IP v6 addresses (labeled inet6 addr), but those are not commonly used.
Press WINDOWS+R (where WINDOWS is the "Windows Key", the one with the flag) to pull up a "Run Program" dialog, then enter cmd to get a command prompt window. Now enter ipconfig /a. This should give you all the information you need.
In order to prevent subjects from fiddling around with the web browser used to display a user interface to them, you can use a "kiosk mode" web browser. While several web browsers have kiosk modes, I have found that Google Chrome is the most convenient. On Linux, you simply use the command line google-chrome --kiosk instead of just google-chrome, and you get a full-screen browser without any extraneous bits of user interface that subjects might accidentally click on.
The first thing that should strike you when looking at these files is that there’s not very much there. This is on purpose, and took a lot of work. It is my experience that the number of bugs per 100 lines of code is roughly constant, and that the best way of limiting the number of bugs is to limit the amount of code. (In the extreme case, of course that means that the only way to have no bugs is to write no code. This is not as vacuous an observation as it seems: it pays to think twice before deciding to turn something into a computer program in the first place.)
# Willow, a Python framework for experimental economics. Copyright (c) # 2009, George Mason University. All rights reserved. Redistribution # allowed under certain conditions; see file COPYING.txt # WILLOW ############################################################# # This file is a library that you can use to write a server. You use # such a server in combination with a client. The client is always a # web browser displaying willow.html and running willow.js. None of # this client-server business, however, is germane to the way you # ought to think about writing a Willow application, though: you can # write your application as though you were using a regular old GUI # toolkit and there wasn't a client/server architecture or a network # in the first place. # The comments in this file are meant for people who have some # experience with distributed systems and want to hack Willow # itself. If you merely want to USE the Willow library to construct # your own applications, read the manual instead. import json, BaseHTTPServer, time, Queue, mimetypes, SocketServer import threading, sys, csv, os, os.path, copy, re, stat # LOGGING ############################################################ # This section provides the code that produces the output files, which # go in the log/ directory. # The file names for output files are constructed so as to work on all # platforms. This means we use os.path.join to insert the right path # separator, and we do not the ':' character, which has a special # meaning on Windows (as in "C:\"). All output is unbuffered # (bufsize=0) and synchronized on a single mutex. This code SHOULD be # unicode-safe (important if we want to use it in, say, China), but I # haven't tested that very much. _log_fn = os.path.join("log",time.strftime("%Y-%m-%d-%H-%M-%S")) _log_csv = csv.writer(open(_log_fn + ".csv","w",0)) _log_txt = open(_log_fn + ".txt", "w", 0) _log_lock = threading.Lock() tbl = [] def log(*msg): with _log_lock: _log_csv.writerow([int(1000*time.time())] + list(msg)) tbl.append(msg) _trace("log",unicode(tuple(msg))) def _trace(tag, *objs): with _log_lock: msg = "\n".join([ ("%s" % d) for d in objs ]) out = "" for line in (msg + " ").splitlines(): for i in range(0,len(line),70): out += " " + line[i:i+70] + "\n" s = "%-4s %2d %s" % (tag, _me(), out[8:]) lines = s.splitlines() if len(lines) > 10: lines = lines[:3] + ["..."] for line in lines: sys.stdout.write(line + "\n") _log_txt.write("%s\t%d\t%r\n" % (tag, _me(), msg)) def _trace_action(obj): tag = obj["action"] msg = "(%s)" % obj["selector"] if obj.get("timestamp", False): msg += " ...timestamp..." if obj.get("delay",0) != 0: msg += " ...%s..." % obj["delay"] if obj.get("css_class", "") != "": msg += " %s" % obj["css_class"] if obj.get("attribute", "") != "": msg += " %s=" % obj["attribute"] if obj.get("value", "") != "": msg += "%s" % obj["value"] if obj.get("content", "") != "": if len(str(obj["content"]))>50: msg += "\n" else: msg += " " msg += "%s" % obj["content"] _trace(tag, msg) # TUPLE SPACE ######################################################## # The tuple space is for communication between session threads, and # for asynchronous messages from the clients to the session # threads. (Messages from the session threads to the clients go # through a system of queues instead, which we will meet in the next # session.) It allows you to write your program without shared state # between threads, and thus without your having to worry about # race conditions. # Conceptually, the tuple space is a multiset of dictionaries, but # Python doesn't have multisets, so we use a dictionary of # dictionaries in which the keys are not really used for much of # anything (they are simply sequentially assigned integers). All # access to the tuple space is synchronized on a condition variable. A # put() operation is a simple matter of inserting a value into the # dictionary and waking up any threads that are blocking on take(). A # deep copy is made of the inserted object to prevent a user from # accidentally sharing data structures between threads by way of the # tuple space; the whole point of the tuple space is to facilitate a # shared-nothing archictecture in which the user need not be concerned # with mutual exclusion! There are both blocking (take()) and # nonblocking (grab()) functions for retrieving (and deleting) # dictionaries from the space, and both of those invoke a simple # linear search. To facilitate future extensions along the lines of # the Metaweb Query Language (both faster-than-linear search if that # turns out necessary and also more elaborate query constructs), I # restrict keys in the dictionaries and in queries to be only strings. _board_space = {} _board_counter = 0 _board_cv = threading.Condition() def put(item): with _board_cv: global _board_counter assert type(item) == dict assert all([ type(key) in [unicode, str] for key in item.keys() ]) _trace("put", item) _board_counter += 1 _board_space[_board_counter] = copy.deepcopy(item) _board_cv.notifyAll() def _find(pop, *patterns): for number, item in _board_space.iteritems(): for pattern in patterns: assert all([ type(key) == str for key in pattern.keys() ]) if all([ k in item and item[k] == v for k,v in pattern.iteritems()]): if pop: _board_space.pop(number) return item return None def take(*patterns): with _board_cv: _trace("take", *patterns) while True: item = _find(True, *patterns) if item != None: break _board_cv.wait() _trace("took", item) return item def view(*patterns): with _board_cv: _trace("view", *patterns) while True: item = _find(False, *patterns) if item != None: break _board_cv.wait() _trace("veow", item) return item def grab(*patterns): with _board_cv: _trace("grab", *patterns) item = _find(True, *patterns) _trace("grub", item) return item # THREAD POOL EXTENSION TO THE PYTHON TCP SERVER ##################### # In order to get decent performance on Windows, we must improve a bit # upon the standard Python TCP server. In particular, we replace # SocketServer.ThreadingMixIn with a homebrew class. # If you want to use the original, you can try this instead: # # class WillowPool(SocketServer.ThreadingMixIn): pass class WillowPool: # By default, we create "non-daemon" threads. daemon_threads = False # The pool is a queue of available worker threads pool = Queue.Queue() # A new worker thread creates a mailbox (i.e. length-1 queue) in # which to receive assignments. It then goes to sleep, but it wakes # up whenever it gets an assignment. When it gets an assignment, it # does the server thing, and then adds itself to the pool to # indicate that it is available again. class Worker(threading.Thread): def __init__(self, server): threading.Thread.__init__(self) self.server = server self.mailbox = Queue.Queue(1) def run(self): while True: (request, address) = self.mailbox.get() try: self.server.finish_request(request, address) self.server.close_request(request) except: self.server.handle_error(request, address) self.server.close_request(request) self.server.pool.put(self) # When a request comes in, we try to get a worker from the pool. If # there are none, we make a new one. Then we tell the worker to # work. def process_request(self, request, address): try: worker = self.pool.get_nowait() except Queue.Empty: worker = self.Worker(self) worker.daemon = self.daemon_threads worker.start() worker.mailbox.put((request, address)) # WEB SERVER ######################################################### # The Willow web server is built on Python's BaseHTTPServer. It uses a # new thread for each request, which is slow on Windows. A thread pool # would be useful improvement. GET requests are served from the file # system, but POST requests are special and assumed to come from # willow.js. They come in three flavors: a newly connected client # POSTs to /new first, requesting a client ID. On this occasion, a # queue is created and inserted into the _clients dictionary # (synchronized on a condition variable) keyed by the new client ID, # and a session thread is started. The queue is for communication # between the web server threads and the session thread. Once the # client ID is determined it is sent to the client, which can now make # to other kinds of POST requests. The first is to URL /put, and this # simply lets the client put something on the tuple space. (The client # objects are JSON data structures, which map directly onto Python # data structures and no further processing is required.) The second # type of POST request from the client is a request for commands, and # these commands the web server gets from the queue corresponding to # the client, where they are put by the session thread corresponding # to the client. If multiple commands are on the queue, they are all # sent to the client at once. The commands are assumed to be # dictionaries and because they are sent in JSON, so conversion from # Python comes (again) nearly free. class Client: def __init__(self): self.queue = Queue.Queue() self.trace = [] def send(self, msg): self.queue.put(msg) self.trace.append(msg) def replay(self): cancellation = Queue.Queue() self.queue.put(cancellation) cancellation.get() for msg in self.trace: self.queue.put(msg) _clients = {} _clients_cv = threading.Condition() def run(session, port=8000): webroot = os.path.dirname(__file__) or os.curdir class Handler(BaseHTTPServer.BaseHTTPRequestHandler): def log_message(self, fmt, *arg): pass def do_GET(self): fns = [ os.path.join(os.curdir, self.path[1:]), os.path.join(os.path.dirname(__file__), self.path[1:]), os.path.join(os.path.dirname(__file__), "willow.html") ] for fn in fns: if os.path.isfile(fn): mime = mimetypes.guess_type(fn) if type(mime) == tuple: mime = mime[0] if re.search(".js$", fn): mime = "text/javascript" if re.search(".css$", fn): mime = "text/css" self.send_response(200) self.send_header("Content-type", mime) self.end_headers() self.wfile.write(open(fn).read()) return def do_POST(self): self.send_response(200) self.send_header("Content-type", "application/json") self.end_headers() request_sz = int(self.headers["Content-length"]) request_str = self.rfile.read(request_sz) + " " request_obj = json.loads(request_str) if self.path == "/new": with _clients_cv: if request_obj < 0: client = 0 while client in _clients: client += 1 else: client = request_obj self.wfile.write(client) if not client in _clients: _clients[client] = Client() thread = threading.Thread(target=session, args=(client,), name=str(client)) thread.daemon = True thread.start() else: _iam(client) _trace("bork", " *** CLIENT %s RESTARTED *** " % client) _clients[client].replay() if self.path == "/put": _iam(request_obj.get("client",-1)) put(request_obj) if self.path == "/do": client = request_obj _iam(client) queue = _clients[client].queue actions = [] try: while actions == [] or not queue.empty(): action = queue.get() if isinstance(action,Queue.Queue): action.put(0) raise Exception _trace_action(action) actions.append(action) self.wfile.write(json.dumps(actions)) except Exception: pass class Server(WillowPool, BaseHTTPServer.HTTPServer): daemon_threads = True allow_reuse_address = True _iam(-1) _trace("run", "Willow is running on port %s" % port) Server(('', port), Handler).serve_forever() def _me(): return int(threading.current_thread().name) def _iam(n): threading.current_thread().name = str(n) # IO ################################################################# # This is where the bulk of the Willow API is: functions that do # nothing but send a command to the client, which then processes the # command in Javascript somehow. Documentation is in the manual. The # one interesting point is that each session thread has one integer's # worth of thread-local storage: the client ID of its corresponding # client. That way, the user can call add(foo) rather than having to # type add(foo,me) all the time. def _action(object, clients): if clients == None: clients = _me() if type(clients) == int: clients = [clients] if "content" in object and type(object["content"]) == file: object["content"] = object["content"].read() if "content" in object: object["content"] = str(object["content"]) if "value" in object: object["value"] = str(object["value"]) for client in clients: _clients[client].send(object) def add(content, selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'add', 'content': content, 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def let(content, selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'let', 'content': content, 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def poke(attribute, value, selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'poke', 'attribute': attribute, 'value': value, 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def hide(selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'hide', 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def show(selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'show', 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def push(css_class, selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'push', 'css_class': css_class, 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) def pop(css_class, selector="body", clients=None, timestamp=False, delay=0): _action({ 'action': 'pop', 'css_class': css_class, 'selector': selector, "timestamp": timestamp, "delay": delay }, clients) _ticket_lock = threading.Lock() _ticket = [0] def peek(selector="body", clients=None): with _ticket_lock: _ticket[0] += 1 ticket = _ticket[0] _action({ 'action': 'peek', 'selector': selector, 'ticket': ticket, "timestamp": False, "delay": 0 }, clients) msg = take({"tag":"peek","ticket":ticket}) return msg['value'] # THREADING ########################################################## # The background() function allows the user to start a new # thread. This adjusts the thread-local stored client ID so that you # can still call add() etc from inside the new thread and they will # know which client to operate on. It also takes an optional delay, so # you can use this to schedule events. Otherwise, it's just your basic # forking operation. def background(function, delay=0): name = threading.current_thread().name def thunk(): threading.current_thread().name = name function() threading.Timer(delay, thunk).start() def sleep(delay): time.sleep(delay)
   <title>Willow</title>    <link type="text/css" rel="stylesheet" href="willow.css" />
/* * Willow, a Python framework for experimental economics. Copyright (c) * 2009, George Mason University. All rights reserved. Redistribution * allowed under certain conditions; see file COPYING.txt */ .hidden { display: none; }
/* * Willow, a Python framework for experimental economics. Copyright * (c) 2009, George Mason University. All rights reserved. Redistribution * allowed under certain conditions; see file COPYING.txt. */ $(document).ready(function(){ /* * The preferred client ID is the URL if that is an integer, or else * 0. We will not know the actual ID until after we haved logged in. */ var url = window.location.pathname.slice(1); var preferred_client = url ? Math.round(url - 0) + "" : "-1"; /* * Now log in. */ $.post("new", preferred_client, function(client) { /* At this point we are logged in, and we know the actual client * number. First, we will define a few helper functions, and then * we will start listening for server requests.*/ /* * This function makes a call back to the server to post a * dictionary on the board. It is used both for requested (tag=peek) * and automatic (tag=click, tag=key) dictionaries. It decorates the * dictionary with two additional entries that indicate (i) client * number and (ii) a time stamp; these are used in all dictionaries * posted by the client, so we might as well just code them once. */ function put(obj){ /* * Keep in mind that client is a string and we want an integer * here, so subtract 0. */ obj.client = client - 0; obj.time = (new Date()).getTime(); $.post("put", JSON.stringify(obj)); } /* * Catch keypresses no matter what is in focus and post them to * the board. We can do this once and for all, because all keypresses * accrue to the document object, and there is only one such * object. (Other event handlers are adjusted every time the page * content changes.) */ $(document).keypress(function(e) { if (e.which) put({"tag": "key", "value": String.fromCharCode(e.which)}); }); /* * This function is to be called on newly inserted or modified * HTML elements. It makes sure that the correct event handlers are * bound. This works better than trying to use the jQuery system of * live events. */ function decorate(elt) { /* * Key presses that happen when a text field is in focus * should be processed the normal way and should not result in * events being reported to the server. */ var text_fields = elt.find("input:text,textarea"); text_fields.keypress(function(e) { e.stopPropagation(); }); /* * When somebody clicks a button, or a "clickable" element, we * catch the click and report it. */ var buttons = elt.find(":submit,:button,.clickable"); buttons.unbind("click"); buttons.click(function (e) { put({ "tag": "click", "id": e.currentTarget.id}); }); /* * When an element is marked with class "bait", we want to * turn on class "mouse" whenever the mouse is over it. (This * is for implementing "hover" effects.) */ var mousetraps = elt.find(".bait"); mousetraps.unbind("mouseenter"); mousetraps.unbind("mouseleave"); mousetraps.bind("mouseenter mouseleave", function(e) { $(e.target).closest(".bait").toggleClass("mouse"); }); } /* * This function processes a list of commands received from the * server, and then immediately asks for more commands. */ function action(cmds) { /* * Process each command. */ for (i in cmds) { (function () { var cmd = cmds[i]; function thunk() { switch(cmd.action) { /* * Most of the commands correspond directly to jQuery * methods; we call decorate() on the result to make sure that * new/modified HTML elements have the right event handlers * bound. */ case "add": decorate($(cmd.selector).append(cmd.content)); break; case "let": decorate($(cmd.selector).html(cmd.content)); break; case "poke": decorate($(cmd.selector).attr(cmd.attribute, cmd.value)); break; case "push": decorate($(cmd.selector).addClass(cmd.css_class)); break; case "pop": decorate($(cmd.selector).removeClass(cmd.css_class)); break; case "hide": $(cmd.selector).hide(); break; case "show": $(cmd.selector).show(); break; /* * The "peek" command is a request for the contents of * some input element to be posted to the tuple space. * jQuery has a method .val() that will get the content * of all sorts input elements; quite convenient! */ case "peek": var elt = $(cmd.selector); if (elt.size() > 0) { var val = elt.eq(0).val() || ""; } else { var val = ""; } put({"tag": "peek", "ticket": cmd.ticket, "value": val}); break; } /* * All commands can come with an optional request for a * timestamp to be posted; the put() function puts on the actual * timestamp. */ if (cmd.timestamp) put({ "tag":"timestamp" }); } /* * If cmd.delay > 0, the request is for the command to be * scheduled rather than executed immediately; that's easy * enough to handle using window.setTimeout. */ if (cmd.delay > 0) { window.setTimeout(thunk, 1000 * cmd.delay); } else { thunk(); } /* * The use of an anonymous function that immediately gets * called may seem strange, but it's a workaround for Javascript's * dyslexical scoping (pun intended). */ })(); } /* * Request more commands. (At your service!) Note how the loop * works: we the action() function registers itself as a * callback. This is NOT recursion and will NOT overflow the stack. * This here trick, BTW, is known under various highfalutin names such * as "Comet" and "reverse AJAX". */ $.post("do", client, action, "json"); } /* * Request some commands to set the ball rolling. */ action([]); }); });


Mengetuk Pintu Langit
Choose a Room
Daily Design Metting - Metting Room No.1
Single
Double
Organization Day
Time Open
8:00am - 10.00am
9:00am - 21:00pm
10:00am - 22:00pm
12:00am - 24:00pm


{{fun.zone.name}}
{{fun.zone.description}}
ALEX: the app
QUIZ: How Well Do You Know Alex?
His first name (case sensitive):
His last name (case sensitive):
Male
Female
His appearance
Hairy
Homeless
Hefty
Healthy
His personality
Nervous
Nosy
Nice
Needy
Results
{{finalresult}}
{{percentright}}%