text:
Week 4, ladder of abstraction
This is an edition of Robin Sloan's video game development diary.
Welcome: to returning readers as well as everyone newly subscribed. If you missed it, week 1 sets up the motivation behind this project. All the previous editions are available over on my blog.
The k in the headine at the top of the page doesn't even look wonky anymore. It's all the other letters that are wonky.
White Mice Playing, Kubo Shunman, ca. 1816
No fun 3D animations in this edition; no maps, no pixels. This week, it's all about words.
This edition will be looser than usual—therefore: quite loose indeed—because I'm going to work through some ideas as I write it. In the first edition, I told you
the sensibility here is definitively "you are working in the studio with me"
and this week you will learn that the sensibility might sometimes even be "you are in my brain with me." Currently, my brain sounds like this:
Your browser can't play my sound clip! Alas.
That is the second and most current version of Jesse Solomon Clark's "Green Goat homecoming theme," the meaning of which you'll understand by the time you get to the end of this edition.
Wot I got
An important milestone draft, which, at the end of this newsletter, you will have the opportunity to read, if you wish.
The Devil's party
Just to quickly re-orient:
Perils of the Overworld aims to be an adventure game in which you set out on a grand, dangerous quest but then, as you aid others and are aided in return, find yourself enmeshed with them: and so, your quest ends not in the jaws of a dragon but in the grip of a community. In the vise of actually caring! Which is, of course, wonderful, and which sets up a tension, I hope, between "winning" the game and "losing" the game. Losing will be pleasant and interesting. You'll do it over and over.
The questing and caring play out in a medium-to-high fantasy universe, brazenly pastiche, homage to the books of my youth as well as the cozy, mashed-up settings of Japanese video game RPGs.
That is, however, still a very broad scope! What IS this world, exactly, and what kind of voice describes it?
First, where worldbuilding is concerned, I am of the Devil's party, which is to say, M. John Harrison's. More than a decade ago, he wrote:
Every moment of a science fiction story must represent the triumph of writing over worldbuilding.
Worldbuilding is dull. Worldbuilding literalises the urge to invent. Worldbuilding gives an unneccessary permission for acts of writing (indeed, for acts of reading). Worldbuilding numbs the reader's ability to fulfil their part of the bargain, because it believes that it has to do everything around here if anything is going to get done.
Above all, worldbuilding is not technically neccessary. It is the great clomping foot of nerdism. It is the attempt to exhaustively survey a place that isn't there. A good writer would never try to do that, even with a place that is there. It isn't possible, & if it was the results wouldn't be readable: they would constitute not a book but the biggest library ever built, a hallowed place of dedication & lifelong study. This gives us a clue to the psychological type of the worldbuilder & the worldbuilder's victim, & makes us very afraid.
I find this formulation both cautionary and invigorating. The message, as I receive it, is that the words are all there is. You cannot substitute exhaustive backstory for language that crackles and conjures. That's the cautionary part: don't try to compensate for your cruddy sentences with an intricate magic system.
The invigorating part is: the words are all there is! And if that's true, then words are all you need, and, my gosh, what LEVERAGE.
I will once again invoke the great one, Ursula K. Le Guin, who, near the end of A Wizard of Earthsea, wrote:
But … nothing is told of that voyage, nor of Ged's meeting with the shadow, before ever he sailed the Dragons' Run unscathed, or brought back the Ring of Erreth-Akbe from the Tombs of Atuan to Havnor, or came at last to Roke once more, as Archmage of all the islands of the world.
This is a perfectly seductive sentence; it is exactly what you want to read in a book about wizards and sailboats. And: at the time she wrote it: Le Guin had no idea why a person would sail the Dragons' Run, or what the nature of the Ring of Erreth-Akbe might be. That doesn't mean it was a random linguistic spasm; Ursula K. Le Guin knew how to write a great line, obviously, and WHEW could she name a charismatic entity. I mean, "The Tombs of Atuan" is so good it became the title of the next book in the series.
But the point is, there was no hulking sourcebook lurking behind that sentence. There was just: the sentence. One moment there was nothing, and the next there was:
or brought back the Ring of Erreth-Akbe from the Tombs of Atuan to Havnor
Less than twenty words; there's your sourcebook right there.
So, that is all to say, POTO's world will be built a sentence at a time. In the draft that I will share with you at the end of this edition, you'll find this line:
a hundred barrels of cider bound for the fifth division of the second army of the Gregarious Empire
and, while I had no idea what the Gregarious Empire was when I wrote it, it will not surprise you to learn: now I want to find out.
For me, this is very nearly the entire appeal of writing. Other people are drawn to fiction—reading it, writing it—for different reasons, and that's fine. Me, I live for the leverage. Somehow, a few curling symbols on a page or a screen can conjure a sweeping imperial history. They don't do it alone; they draw on the deep well of everything else you've ever read and heard. Even so: what a magic trick. I love it. I am committed to it.
So: worldbuilding, sorted.
The more vexing challenge has been the game's voice.
Outfit for Travel, Kubo Shunman, ca. 19th century
There was, and there was not
I've always thought of a piece of fiction's voice as its overall "stance towards the world." My novel Sourdough has a voice that is zoomed-in, personal, wry, up-to-the-minute contemporary. My story The Writer & the Witch has a voice that is zoomed-out, all-knowing, timeless, a bit melancholy.
The voice I'm going for in POTO is some version of the latter: the voice that intones, "Once upon a time…" and you believe it. (Or, to use another great stock opening line: "There was, and there was not." I like that one even better.)
In the introduction to his recent-ish translation of Fairy Tales from the Brothers Grimm, Philip Pullman quotes the poet James Merrill:
I yearned for the kind of unseasoned telling found
In legends, fairy tales, a tone licked clean
Over the centuries by mild old tongues,
Grandam to cub, serene, anonymous.
"Serene, anonymous." That's it exactly.
The thing is: I have been having a LOT of trouble with this voice, which calls for not only a certain register but a looseness with time; it calls for sentences like
Ninety-nine years rushed under the short stone bridge, and the writer's life and legend grew together.
You might recall that POTO relies on a programming language called Ink to control the story's flow. Many times this week, I squared up to wrestle with my Ink document, writing one module after another, just absolutely unsatisfied with how it all sounded, how it all felt.
I was bogged down in "this, then that."
It is one of the commonest traps for the fiction writer; I have fallen into it many times before. "This, then that" means the action proceeds forward at a constant pace, locked into a single temporal resolution. I'll write a dorky example:
I walked outside. The streets were empty, except for a man in some kind of jumpsuit, blue and green—maybe from the power company. He wore a mask, too, which reminded me to pull mine up over my ears. I felt stiff from lack of exercise. At the crosswalk, I waited for the light to change, wondering why I bothered. Up the street, a siren wailed.
It's not horrible, but it goes thud… thud… thud. This, then that. This, then that. The monotony only grows if you keep it up over paragraphs and pages.
There is none of the arcing electricity that I find in my favorite fiction.
Here's another version of the ~same scene:
A week in isolation. For most of it, I picked crumbs off my belly. Five seasons of Dragon Gear Saga Excelsior and I wasn't even halfway done. When I ventured outside at last, there was just one other pedestrian, wearing a blue and green jumpsuit that made me think of Ylys the Wyrm-Knight. While I waited for the light to change—why?—I spelled it in my head. Y-L-Y-S. Y-L-Y-S. Thank goodness for subtitles. Up the street, a siren wailed.
Neither of those passages is high art, BUT, the thing to notice about the second version is the way its clock is more elastic and how that opens up opportunities to make little associative leaps across time, space, memory, culture—everything.
Years ago, I had a great writing teacher, Roy Peter Clark, who taught me about "the ladder of abstraction." In his book Writing Tools—which I have given as a gift more times than any other book in existence—Roy writes:
Good writers move up and down a ladder of language. At the bottom are bloody knives and rosary beads, wedding rings and baseball cards. At the top are words that reach for a higher meaning, words like freedom and literacy. Beware of the middle, the rungs of the ladder where bureaucracy and technocracy lurk. Halfway up, teachers are referred to as full-time equivalents and school lessons are called instructional units.
You can read Roy's entire (short) chapter about the ladder of abstraction at Google Books, and I recommend it. (I mean: if you're interested in the craft of writing, you really need to just get this book. One of the things that makes Writing Tools so convincing is that it is, itself, literally perfectly written.)
So, a sentence plucked from the top of the ladder of abstraction might be
The Gregarious Empire was without rivals for a thousand years.
While a sentence grounded at the bottom might be
A toad croaked from its shelter in the hollow of a rusted helmet.
Both of those are great! A vast empire—cool! A lil toad—nice! As Roy tells us, there's good stuff at both ends of the ladder. Even better, there's a huge amount of energy in the transition between them, as you zoom from historical abstraction to telling detail and back again.
In the ladder's bland middle, things are neither thrillingly broad nor crunchily specific. And, unfortunately, the middle is where "this, then that" lingers.
I am making a video game, but/and it will succeed or fail, as surely as a novel would, on the quality of its prose, and my Ink drafts were stuck there in the bland middle. The player walked into town; decided where to explore; searched for an inn; gathered information; decided where to explore after that… ugh. It was the turn-by-turn trudge of a mediocre Dungeons and Dragons session.
To make matters worse for myself, I had been reading Hero Legends of the World, which I have shown you before—
—and it was AWFUL, because it was wonderful. These stories, as retold by Hans Baumann and translated into English by Stella Humphries, are completely gonzo and perfectly concise. Their "worldbuilding" is utterly telegraphic. Look at this opening paragraph; look how fast it moves, how instantly it conjures itself:
So here I am, reading Hero Legends, reading Pullman's Grimm, rereading my own plodding Ink, trying again, producing nothing better, getting frustrated, and, honestly, despairing a bit, which is almost always a sign that you need to take a step back.
That's what I did. I closed the Ink editor and, instead, just… Wrote Something The Normal Way. And, almost immediately, it worked. The whole scene tumbled out, in almost exactly the right voice, casually informing the reader that a year had passed, and another, and another. It moved up and down the ladder of abstraction. It became unstuck.
Here is the draft that I produced. I can't say I really recommend reading it—I mean that sincerely—but it felt like a breakthrough, so, in the spirit of "working in public," I thought it might be interesting, even useful, to share.
As soon as it emerged, I sent it to my collaborator Jesse Solomon Clark, who replied, in classic Jesse fashion:
Just posted a tune in response to this draft. Sort of a Port Fabri tavern string band contentment theme.
So if you DO read this draft, you are obligated to enjoy it alongside this week's
Sound snack
which is the initial version of Jesse's tavern string band contentment theme :')
(Now go back to the top of this newsletter and compare it to the second version, which he sent over Saturday night.)
The draft I've linked above truly is a DRAFT, unpolished and unfinished, wonky in all the ways, but the important thing is that it made me say, oh, there you are: the voice I've been looking for. Or, at the very least, a signpost pointing the way toward that voice.
A block of prose Written The Normal Way isn't a game; it's hardly game-like at all. But it does represent a sequence of events and a collection of feelings that I want the reader-player to experience. So, the question becomes: can I now transform this Normal Prose into Ink: stepwise, branching, explorable? I believe the answer is yes, but/and
Wot I'll do
this week is: find out.
From Oakland,
P.S. Did you want to see the rest of my mythopoetic hoard? I THOUGHT YOU MIGHT
I don't know how anybody writes without a Dictionary of Fairies close at hand…!
This has been an edition of my video game development diary, sent by email every few weeks. You can subscribe:


text:
Google to spin off search marketing side of Performics
by Matt Cutts on April 2, 2008 in Google/SEO
I'm crunching on a bunch of work stuff today, but I wanted to point out this official Google blog post briefly:
Since we closed the acquisition of DoubleClick on March 11, we've been immersed in integration planning for each of our products and business units. Recently we completed this process for the DoubleClick Performics businesses, and have decided to split them into two separately-run business units: Affiliate Marketing and Search Marketing.
It's clear to us that we do not want to be in the search engine marketing business. Maintaining objectivity in both search and advertising is paramount to Google's mission and core to the trust we ask from our users. For this reason, we plan to sell the Performics search marketing business to a third party.
I have nothing but respect for the people that do search marketing for Performics, but I think this is the best decision. People hold Google to a unbelievably high standard, and I think it's important that we try very hard to avoid any conflict of interest — or even the appearance of conflict of interest — in our business. Many people I respect have wanted Google to take this step and I think it's the right call.
(As always, remember that this is my personal blog and personal opinions.)
51 Responses to Google to spin off search marketing side of Performics (Leave a comment)
Harith April 2, 2008 at 3:24 pm
Very wise decision from Google side.
Jaan Kanellis April 2, 2008 at 3:38 pm
Nice to hear it official.
Michael Martinez April 2, 2008 at 3:47 pm
Thanks for the update. "Update on Performics", I mean.
Steaprok April 2, 2008 at 4:08 pm
Hey Matt-
I'm really glad to hear this, I think it removes the shroud of impropriety from Google. It allows for a healthy SEO/SEM industry to thrive alongside Google.
Josh April 2, 2008 at 9:40 pm
Are Google employees allowed to do affiliate marketing on the side while working at Google? At one point a few years ago, I remember this being encouraged by the Google Adwords team?
Nick - I think the original Nick here. April 2, 2008 at 9:42 pm
Just wanted to add my approval of this move as well. Great decision by Google.
Dave (original) April 2, 2008 at 10:16 pm
Bah! Don't cater to the tin-foil hat brigade. Most "SEO/SEM" companies are nothing but Spammers and they NEED an ethical leader as apposed to the black hat "leaders" who have a vested interest in SE spam.
I agree with most decisions from Google, but not this one 🙁
For this reason, we plan to sell the Performics search marketing business to a third party
I hope not to the highest bidder and you ONLY sell to someone with a proven track record in ETHICAL SEO. That excludes 99% of the so-called "SEO" out there now.
Ankit April 2, 2008 at 10:18 pm
Great news .. Yipeeeeeeeee !! Party Time !! Every one invited 😉
mark April 2, 2008 at 10:20 pm
Great call! Good to hear this.
Tonnie Lubbers April 3, 2008 at 12:30 am
It is the only desicion Google could have made without loosing credibility.
And yes, people do hold Google to a unbelievably high standard, that means it is doing something good. Otherwise people wouldn't care, would they. 😉
Mikkel deMib Svendsen April 3, 2008 at 1:03 am
Good call! Now we are happy at Strikepoint again. Expect a "We like Google" show on monday" (and no, that won't be the first, Matt :))
Maurice April 3, 2008 at 1:11 am
nice to see a company do the sensible and right thing for a change pity that my old employer BT did not do the same over the Phorm debacle.
ThomasB April 3, 2008 at 3:07 am
What about DART Search? 🙂 I guess having inside knowledge on algorithms makes it a lot harder to keep the standards that high …
Aaron April 3, 2008 at 5:09 am
I'll buy it… Let's see here, I've got (thirty… forty… forty-three)….
Er, is Google willing to take a loss? 😉
Jim McNelis April 3, 2008 at 5:52 am
Glad to hear it. And yes, we hold Google to an unbelievably high standard. Thank you for living up to that standard yet again.
Farhad April 3, 2008 at 6:37 am
I'm glad to see this. The fact that Google owned an SEM agency for a while was a good cause for us to be worried. Now we shall worry no longer.
Hmmm April 3, 2008 at 6:39 am
Hey Dave (original)… I think I'll give you an 'I told you so!'
And yes, very glad to see this happening. Very glad.
Good on you Google, for doing the right thing.
SEOMike April 3, 2008 at 6:51 am
"Crunching on some work stuff" You sure are! I'm trying not to get an ulcer as I try to figure out what's going on with Dewey.
Oh, nice job on those posts yesterday. You had me for a couple of seconds. I was ready to shove my iPod in my PCMCIA slot 🙂
PS… hang on to your iPhone. I dropped mine the other day and a third of the screen shattered. I had to get one of those stick-on protectors to keep the glass in the screen. It's a $250 repair. I might just wait for the 3G version.
Catfish April 3, 2008 at 12:52 pm
Excellent decision.
spamhound April 3, 2008 at 2:22 pm
Have you moved to a new department in Google? I wonder this because the results lately are not reflective of discounting paid links. In fact, paid links seem to of really been given a boost in this latest shift.
That and you never really seem to talk about spam stuff anymore. Or at least not as often as you used to.
Makes me wonder if you have moved on to other things.
Jayson April 3, 2008 at 7:12 pm
Yeah I think it's the right call too. As you mentioned, Google is held to extremely high standards (for good reason). Keeping the company would do nothing more than create a PR nightmare – atleast within the online community. It's the best decision though I'd love to have Google helping our company with optimization.
Simon April 3, 2008 at 8:02 pm
Good call Google. However, it does highlight the fact that Google paid over $3 billion for a shed-load of DC data, I wonder what that they're going to do with that…
purposeinc April 3, 2008 at 8:06 pm
Matt, If you have a minute please check my blog for an important open source announcement. (Also all fellow Cuttlets are also invited)
Dave (original) April 3, 2008 at 9:50 pm
Nowhere near. You were spouting tin-foil hat conspiracies that were unfounded. This now proves beyond any doubt that the "conspiracies" were in you mind 🙂
In fact, it was ME that told you to stop worrying and stop believing all the crap out there on SEO blogs and forums.
Whether Google sell or keep Performics there is absolutely NO WAY Google would have frigged their own SERPS.
Ben April 4, 2008 at 1:46 am
So was this takeover for receipt of a massive amount of usage data?
Tonnie Lubbers April 4, 2008 at 2:06 am
@Dave(original)
That was never the question. The posibility was!
Dave (original) April 4, 2008 at 3:57 am
Tonnie Lubbers, no idea what you are trying to say.
@Dave(original),
You stated:
My anwser to that:
Fionn April 4, 2008 at 7:38 am
Blasted housing market if my equity was'nt upside down I might go after them myself. Good call from Google. I wonder what Wall Street thinks, not that I really care this is definitely the right thing for Google.
(Tonnie got it on the head, that is. Not you, Dave. Your loathing of SEO has clouded your mind, young Padawan.)
Tonnie Lubbers, it WAS a question for the tin-foil hat brigade. AKA Hmmm.
I have been stating from the moment they purchased, Google would never do so. But, conspiracy theorist don't like common sense and would rather believe all the SEO blogs/forums that post selve-serving factoids.
Your loathing of SEO…..
I loath black-hats, so yes, I do loath most so-called "SEO".
The FACTS are quite simple for ANY website. That is, adding well informed unique content pages frequently and aim to become THE site for your chosen topic. Do that and you actually get REAL VOTES rather than links of little value or short term value.
The above approach has worked ever since Google became change the way SE work and will continue to work in the future.
SE0Rocket Science, despite most in the so-called industry preying on the uniformed and stating otherwise.
"SE0Rocket Science" SHOULD be SE0 is not Rocket Science….
Ash Nallawalla April 4, 2008 at 11:01 pm
"It's clear to us that we do not want to be in the search engine marketing business."
A lot of people believe that AdWords/YSM/adCenter = Search Engine Marketing (SEM), so this is an unfortunate slip of the tongue. Didn't he mean "SEO"?
Ash, for many, SEM/SEO are one and the same. While SE's do supply a *methods* (AdWords etc) for marketing, big to medium companies often pay someone to get the best ROI from their marketing campaigns.
IMO, the ENTIRE SEM/SEO industry is in desperate need for *ethical* leaders. The ENTIRE SEM/SEO industry has been BADLY tainted over the years, thank to the so-called current leaders having a vested interest is SE spam.
Harith April 4, 2008 at 11:49 pm
"IMO, the ENTIRE SEM/SEO industry is in desperate need for *ethical* leaders."
But SEO/SEM industry has already a bible and an ethical leader 🙂
Ash Nallawalla April 5, 2008 at 1:22 am
Dave (the original),
Actually, I (and Wikipedia, Webmasterworld and SEMPO) know that SEM = PPC+SEO, but Google, Yahoo and Microsoft have sculpted SEM to mean only PPC. Therefore much of the ad industry that supports PPC advertising is full of people who will potentially be alarmed to hear that "Google doesn't want to be in the SEM business".
It was just a subtle dig. G'day Matt.
Hmmm April 5, 2008 at 12:09 pm
99% of SEO isn't black-hat — I mean, come on… Now THAT is tin foil wearing paranoia — welcome to the Brigade, you'll find your uniform down the hall and to the right.
It's time consuming, and therefore not something most companies, major sites, etc. are willing to do on their own. Coming up with appropriate alt text, meta data, good & unique content that's also well-optimized to reach a specific audience, yadda, yadda, yadda….
Much of SEO just boils down to good writing, actually. The same way I would work on the critique of a piece of literature for weeks or more during grad school… A poem is easy to write. A GREAT poem can take years.
Most businesses, or webmasters, or whatever don't have the time to focus on making great poems. (*metaphor alert*)
You are right is probably isn't quite that high. I'd say MOST use black-hat methods. Sorry, you have to find other recruitments for you tin-foil hat brigade 🙂
It's time consuming, and therefore not something most companies, major sites, etc.
NOT if the person writing the content knows the topic at hand. For example, old Joe who has fished a certain creek all his life would likely use FrontPage etc, to write HTML content pages on the subject and other than submitting to a few Directories, would bother with ANY "SEO". By contrast, most "SEO" would waste time by chasing links and anchor text (obsession with most). BUT "old Joe's" unique and quality content would survive long term and no doubt end up number 1 for related terms. Why? Because it WOULD attract true votes from other similar sites.
Bottom line? Knowing your subject well is far more important than knowing "SEO". If you don't know the topic well, you are better off hiring a professional writer/researcher. Likely a LOT cheaper too with a higher ROI.
Those who search Google want relevant, quality unique content over the most optimized page for a Search Engine. Google and *some* others know this, but most of the "SEO" industry are in vested denial.
Castles built on sand 🙂
would bother with ANY "SEO".
*wouldn't* bother with ANY "SEO".
Matt Cutts April 5, 2008 at 11:14 pm
Ash Nallawalla, that's probably the sentiment that he was going for, or perhaps to emphasize that avoiding conflict-of-interest on the paid search side was important too, because he did mention maintaining objectivity in the paid search side as well.
@Dave(not so original any more)
Stating some one is wearing a the tin-foil hat doesn't bring a discussion any good. Sentiments can be easily misinterpreted. Especially those stating you know what others bare in mind.
Further more, Google knew they were buying a company that had an SEO division. They from the start could have known it would shed an akward light on their acquisition.
Hmmm April 6, 2008 at 4:22 pm
Perhaps he believes that being stubborn, and dismissive of contrary opinions will be an effective way to solicit a job offer from Google?
(From what I know of how Google works, and what they look for in candidates, I doubt it.)
They're looking for critical thought, and original approaches, backed by data.
The sort of thinking that led to them deciding that it's best to call a spade a spade, and divest themselves of a conflict of interest. A mature approach (i.e. one that doesn't include name-calling) wins out in the end.
By the way:
"Those who search Google want relevant, quality unique content over the most optimized page for a Search Engine."
Huh??
This is a false dichotomy.
Since when are these necessarily mutually exclusive?
A winning combo lies in achieving both. Much of SEO lies in making a site easy to use and navigate for BOTH SE's AND users…
Alt tags for instance are essential for making a site accessible to people with visual impairments, etc. etc. etc.
health April 6, 2008 at 6:48 pm
Hmmmm and Tonnie, you are both making quite a few false assumptions. But, who am I to spoil a funny story with facts 🙂
RE: @Dave(not so original any more)
I guess that does "a discussion any good" ? Does the word "hypocrite" have any meaning to you?
RE: This is a false dichotomy.
Nope, perhaps in you mind it is. Google seeks out what its human searchers want/need. You can optimize for search engine algorithms, based on the multitude of factoids, rumors, and best-guesses out there, if you wish, but it is MUCH better, less risky and easier to optimize for humans based on good old common sense. You can also rest assured that any algo tweaks/changes are in your favor. As I said;
Knowing your subject well is far more important than knowing "SEO". If you don't know the topic well, you are better off hiring a professional writer/researcher. Likely a LOT cheaper too with a higher ROI.
Most in the SEO industry have built on VERY sandy foundations and those should start educating themselves if they wish to last long term.
You got the point. And then start to call again.
*plonk*
I take your non-responsive rhetoric as a yes.
For someone soooo sensitive, you sure like to dish it out. Those living in glass houses………….. 🙂
You may take my non-response as an "I have better things to do than beat a dead horse."
I have better things to do than beat a dead horse.
Lauren N Bridges June 16, 2009 at 10:50 am
Hi Matt! As usual, great insight and I love reading your blog. This is a bit off topic but I wanted to share some info about a new tool my company has created for SEM… http://www.usonetworks.com/articles/sem-call-tracker-to-complement-video-search-engine-marketing-optimization-services/
Muhammad Panji April 28, 2010 at 4:08 pm
So just the search marketing division that will be sold? and the affiliate marketing still with Google?
← Okay, enough foolishness. Back to work.
How to use a notebook: 7 quick tips →

redpajama_set_name: RedPajamaCommonCrawl


text:
Has Wreckage From Missing MH370 Been Found?
By Christian Bryant
and Matt Moreno
French investigators are inspecting a wing flap that could be wreckage from Malaysia Airlines Flight 370, which disappeared in March 2014.
French investigators on an Indian Ocean island are trying to figure out whether a wrecked wing flap that washed ashore belongs to Malaysian Airlines Flight 370. If it does, it would be the first big break since the plane disappeared more than a year ago.
The wreckage was found on Reunion Island, a French territory east of Madagascar. Investigators said the wing flap is consistent with those found on a Boeing 777 — the same model of plane that disappeared.
A reporter for local news outlet Linfo.Re tweeted about a suitcase found Thursday morning in the vicinity of where the possible wingtip washed up.
While the find is promising, investigators still have more work to do to be sure the wreckage is from MH370. They must first ensure it's from a 777. A French aviation expert says part numbers and product codes could help make that link. (Video via Boeing)
And then there's the matter of figuring out where the debris came from: Reunion Island is thousands of miles from any suspected crash sites.
Malaysia's prime minster said the location where the debris was found is "consistent with the drift analysis provided to the Malaysian investigation team."
Malaysian investigation teams are now heading to Reunion Island and Toulouse, France, where the debris is being shipped.
The MH370 disappeared in March 2014 flying from Kuala Lumpur to Beijing. 239 people were on board.
This video includes images from Getty Images and NASA.


Lily is a 10 year old female liver & white patched female GSP. Her family had gotten her when she was less than 1 year old and recently decided they had made a mistake. They didn't have the time to give her. While they were able to manage her for almost ten years, they felt she would now do better with a family that would spend more time with her giving her the attention and exercise she required.
While at work, the family kept Lily in a kennel in the backyard where she stayed each day waiting. When they came home, she was let out and would run the property line. Unfortunately, she found a way out of the one acre yard and continued to dig her way out when left unsupervised in the evenings.
Since we have had her, there haven't been any attempts to escape. However, she is getting regular walks and spending time in the field with other dogs. Lily has gotten along well with all the dogs she has met in the field. While she hasn't actively engaged others dogs to play yet, we suspect from her behaviors, she might any day.
Lily came from a home with another dog and cats. While we haven't formerly cat tested her, she has done well around her foster family's cat leading us to believe she would do well in a home with cats. Although, we would still recommend the initial encounters are supervised and done in a controlled environment.
The first night in her foster home, Lily spent the night in the crate. She did well. Lily hasn't yet figured out the doggy door but we suspect she will soon. She approaches the opening, with the flap held up, with caution. Although she doesn't know how to use the doggy door, she hasn't had an accident. Now she spends her nights on a dog bed and waits to go out in the morning.
Lily knows "sit" and "wait". She's very responsive and, even though she appears timid, she is eager to please. She is currently learning "wait" and "do your business". This girl could possibly be taught several new commands as well as a few new tricks.
While Lily is active, she doesn't appear to need a tremendous amount of exercise. A good brisk 20-30 minute walk seems to work magic on her. She is also being trained to run along side the bike but prefers to walk at a fast pace. The bike is such a great way to exercise dogs – even if they just prefer to walk quickly!
3) Become a Rescue Hero! With our limited resources, your monthly donation helps our all volunteer organization continue rescuing German Shorthaired Pointers.


text:
Confusion Building as New Vax Proof Mandate Goes Into Effect Today
John McKay Published: November 15, 2021
When it first came out, several media outlets on the west side reported Gov. Inslee considered his new indoor-outdoor vax proof mandate as an "incentive."
Actually, it's more browbeating by forcing people to consider the vaccine if they want to attend an event, but that's another story.
GOVERNOR THINKS REQUIRING PROOF OF VACCINE IS AN INCENTIVE
In mid-October, Gov. Inslee said all indoor events (sports, concerts, school plays, etc) with 1,000 persons or more were going to be subject to mandatory proof of vaccine, or a negative COVID test no more than 72 hours prior to the event.
Will area HS events be affected? (KSD KaHS)
As KING-5 TV and other outlets reported two months ago, he considers it another of his "incentives." Actually, it's more browbeating by forcing people to consider the vaccine if they want to attend an event, but that's another story.
Going forward from Monday (today) November 15th, all 'public' events, regardless of nature, that have an indoor attendance of 1,000 persons or more will require vax proof or a negative COVID test within 72 hours for you to attend.
We do know this will affect the Western Hockey League, including the Tri-City Americans. Currently, they've been doing better than a number of WHL franchises, especially in Canada. The Am's have been averaging anywhere from 2,500 to 2,700 fans for their first slate of home games. That's not bad considering the mask requirements and other factors.
But now people are wondering how this will be enforced? Especially for public school events.
MOST AREA HS GYMS CAN HOLD AT LEAST 1,000 PEOPLE
We've reached out to Richland Kennewick Schools to find out if they will be basing this upon the capacity size of the facility, OR, will someone actually be standing there with a clicker counting spectators? Will it be based upon ticket sales?
A typical high-stakes HS basketball game can draw upwards of 1,000 fans, especially towards the end of the season.
WHAT ABOUT SCHOOL PERFORMANCES? BAND? CHOIR?
Many parents are wondering about their child's school choir or band performances? Will these be affected? We will update this story as more information becomes available.
CHECK IT OUT: The best county to live in for each state
How Many in America: From Guns to Ghost Towns
Can you take a guess as to how many public schools are in the U.S.? Do you have any clue as to how many billionaires might be residing there? Read on to find out—and learn a thing or two about each of these selection's cultural significance and legacy along the way.
Filed Under: vax mandate
Categories: Events, Health & Fitness
Pasco Councilmember and Hanford Workers Leads Huge Vax Lawsuit
Large Event Promoters Question Hypocrisy of Indoor Vax Proof Mandate
Indoor Event Vax Requirement Doesn't Include Schools, Churches
Leaving Shoes in Vax Mandate Protest? It Will Happen (Again) Thursday in TC


We Wholesale 3 x Mysore Sandal Talcum Powder 10.5 OZ (300 Grams) (3 Bottle), please call/email for details.
Click the button below to add the 3 x Mysore Sandal Talcum Powder 10.5 OZ (300 Grams) (3 Bottle) to your wish list.
You can Buy 3 x Mysore Sandal Talcum Powder 10.5 OZ (300 Grams) (3 Bottle) in our selection of Indian Grocery Online at bargin price of $17.89.


v. t. 1. To fasten on, as armor.
1. To clasp in the arms with affection; to take in the arms; to hug.
Paul called unto him the disciples, and embraced them.
2. To cling to; to cherish; to love.
3. To seize eagerly, or with alacrity; to accept with cordiality; to welcome.
What is there that he may not embrace for truth?
4. To encircle; to encompass; to inclose.
Between the mountain and the stream embraced.
5. To include as parts of a whole; to comprehend; to take in; as, natural philosophy embraces many sciences.
So large a subject fully can embrace.
6. To accept; to undergo; to submit to.
7. (Law) To attempt to influence corruptly, as a jury or court.
v. i. 1. To join in an embrace.
n. 1. Intimate or close encircling with the arms; pressure to the bosom; clasp; hug.


text:
Hartmann Orders ME-LGIP Engines for LPG Tankers
The MAN B&W ME-LGIP engine was unveiled at a ceremony in Copenhagen in 2018
MAN Energy Solutions has won the contract to supply individual MAN B&W ME-LGIP (Liquid Gas Injection Propane) dual-fuel engines to 3 × 5,000-m3 LPG tankers currently under construction by CIMC-SOE (CIMC Sinopacific Offshore & Engineering Co., Ltd.) in Shanghai for Hartmann Gas Carrier, the German shipping company.
Each newbuilding will receive a propulsion package featuring 1 × 5S35ME-LGIP engine with an Alpha controllable pitch propeller, power take-off (PTO) and propulsion control system (PCS). MAN Energy Solutions states that it also expects to introduce its new Triton control platform with the engines.
MAN Energy Solutions' two-stroke licensee, CMD, will construct the engines in Lingang, China with delivery scheduled during the latter half of 2021. The contract contains an option for two further vessels.
The new order is the latest in a series for the ME-LGIP engine. Among these, Oslo-based BW LPG recently exercised an option for further conversions of HFO-burning engines from its fleet to the dual-fuel type. This happened in the wake of the first ME-LGIP retrofit engine enjoying a successful TAT (Type Approval Test) at the works of MAN Energy Solutions' two-stroke licensee, STX HI, in Korea.
Bjarne Foldager – Senior Vice President, Head of Two-Stroke Business at MAN Energy Solutions – said: "After the success of our dual-fuel ME-GI engine running on ethane, orders for our ME-LGIP variant capable of running on LPG are now taking off – a situation we are very pleased with. That the engines in this order form part of an MAN Energy Solutions' package fits perfectly with our desire to increasingly supply complete propulsion solutions."
Foldager continued: "Our low-speed, dual-fuel portfolio has now racked up over 1 million operating hours that owes everything to the strategy we have laid over the past decade and confirms our leadership within this critical marine segment. Our engines' efficiency is the best in the market, which gives shipowners enormous flexibility, and we note that all fuel modes are employed."
Lars Zimmermann, Senior Manager and Head of Two-Stroke Direct Sales, MAN Energy Solutions said: "Despite Hartmann expressing a strong preference for the ME-LGIP, we had to win this order in the face of very strong competition and are, naturally, very happy. The engine is a standard bearer for environmentally friendly, reliable propulsion technology with its seamless switching between fuels and the full rating and performance of the baseline, low-speed diesel engine."
LPG and the ME-LGIP engine
MAN Energy Solutions states that interest in using LPG as a fuel, within and outside of the LPG carrier segment, is growing due to its sulphur-free character, widespread availability and ease of bunkering. In gas mode, the ME-LGIP engine operates on just 3% pilot oil and down to 10% load. Ultimately, the company expects the engine to operate without the need for pilot oil.
The ME-LGIP engine can also burn liquid volatile organic compounds, a deliberate move on the company's part since the IMO will inevitably turn its focus towards the reduction of volatile organic compounds in the future.
The Diesel principle provides the ME-LGIP engine with high operational stability and efficiency, including during load changes and fuel change-over, while defining properties such as a stable change-over from one fuel type to another with no fuel-penalties are maintained. The negligible gas slip of the ME-LGIP engine makes it the most environmentally friendly, two-stroke technology available.
MAN Energy Solutions also reports that the ME-LGIP engine has experienced an up to 18% reduction in CO2 and circa 90% reduction in particulate matter when running on LPG, compared with HFO.
MAN Energy Solutions notes that its portfolio of two-stroke, dual-fuel engines has accumulated 1 million operating hours.The milestone comes on the back of the 300 engines/6.3 GW sales the company recently announced for the segment – all running on clean fuels such as LNG, LPG, ethane and methanol.
MAN Energy Solutions' ME-GI (-Gas Injection) and ME-LGI engines form the core of its two-stroke, dual-fuel portfolio and have notched many notable industry-firsts since their market introduction, including the very first oceangoing ships operating respectively on LNG, methanol, ethane and LPG. To this end, the company recently released a Mk II ME-GI model and are currently, owing to market demand, developing an Otto-cycle variant – the ME-GA.
Based on the experience accumulated over more than 20 years in the development and production of mission-critical electronics, Triton is the new controller platform for MAN Energy Solutions' entire, two-stroke engine portfolio and is a future-proof solution characterised by its modularity, flexibility and scalability.
Having such a stable, flexible foundation for the company's control software will benefit the future direction of its two-stroke technology immensely going forward. Triton delivers extra computing power and a faster network and I/O flexibility to face future demands; it also crucially encompasses cyber security by design.
The Maritime Energy Transition
The ME-LGIP engine ties in with MAN Energy Solutions' belief that it is time for what it terms a 'Maritime Energy Transition' to find clean, decarbonised solutions for seaborne trade and transportation. Essentially, it is the company's call to action to reduce emissions and establish natural gases as the fuels of choice in global shipping. It strongly promotes a global 'turn to gas', driven by the IMO, and a common approach by the shipping industry and politics to invest in infrastructure development and retrofits.


Salted Pink Studio is home to Jessica, an artist who is passionate about all things pink and enjoys good food, great friends, studio time, her family and just about anything glittered, sparkled or salted. Welcome!
I am a Certified Zentangle Teacher® (CZT) and Mixed Media Artist working in Maryland. After crafting a career in higher education administration, I branched out to the art world and now teach recurring Zentangle® classes at a local art studio, and also work with corporate and private clients.
Zentangle is an easy-to-learn, relaxing and fun way to create beautiful images by drawing structured patterns. I became a CZT in 2015 and thoroughly enjoy sharing and teaching this art form. Almost anyone can use it to create stunning, non-representational art. It increases focus and creativity, provides artistic satisfaction along with an increased sense of personal well-being. The Zentangle Method is enjoyed all over the world, across a wide range of skills, interests and ages, and has become a metaphor for deliberate artistry in life.
As a mixed media explorer I use pens, paper, collage, glue, glitter, paint, inks, clay, canvas, crayons, markers, resin, beads, trinkets, napkins, anything! -- sometimes alone but often together, to create fun works of art. It's decidedly fun and a joyous experience to create.
Until a few years ago I never considered myself an artist. Crafty, yes. Artist, not so much. So when I happened upon a Zentangle® class at a local art supply store I was intrigued. Me, an artist? A Martha Stewart Wanna-Be was more appropriate at the time but I took the class anyway. I quickly fell in love with this Zentangle thing and immediately signed up for another class. And another. And then another! I was hooked on this easy-to-learn, simple, intuitive, stunning art form and the Zentangle Method®.
As my "inner artist" grew more confident through tangling it also craved more opportunities. Multiple mixed media, gelli plate and collage classes followed, along with some attempts at traditional painting, clay and assemblage. I took classes locally, traveled to work with artists, asked questions, followed (stalked!) some of my favorite artists on social media, read lots of books and blogs, but always came back to my first love, Zentangle. Oh, yeah. And I also worked my "real" job and raised a kid.
Trained by Rick Roberts and Maria Thomas, the founders of Zentangle, I am now certified to teach tangling and the eight step Zentangle Method. (Yep, that's the CZT after my name -- Certified Zentangle Teacher. It rocks.) I teach at The Queen's Ink in Savage, MD and also offer private classes, corporate seminars, and home parties. It's a perfect activity for craft night, girls' night out (or in), birthday parties, etc. Classes usually last two hours, all supplies are provided, all ages and abilities are welcome. Contact me to book a private event or sign up for a regularly-scheduled class at The Queen's Ink by clicking on the link.
Find/follow me on Facebook or Instagram as SaltedPinkStudio. If you're not on social media, you can see my most recent posts here.
Don't be shy. Ask a question, book a class or just say "hello." Messages are delivered privately and will not appear on the website, but they WILL be read. Pinky promise!


text:
City Cemeteries
Austin Memorial Park Evergreen/Highland Oakwood Oakwood Annex Plummers
All Current Events It's My Park Day Murder, Mayhem & Misadventure Tour	SAC Photo Contest Texas History Tour
Headstone Cleaning & Repair Oakwood Chapel Restoration Oakwood Community Grounds Gravestone Photo Documentation SAC Grant Programs Tours
About SAC Contact Us Join Us Volunteer Shop Descendants FAQ
Save Austin's Cemeteries
PO Box 16411 Austin, TX 78761
Email: info@sachome.org
Meeting Location: Oakwood Cemetery, 1601 Navasota Street
Austin Cemeteries Division (contact to purchase cemetery plots, arrange burials, discuss maintenance requests).
2800 Hancock Dr. Austin, TX 78731 (Business Office hours M-F 8am-5pm (closed from 12 PM - 1 PM for lunch); Cemetery Gates 7am-7pm)
http://www.austintexas.gov/cemeteries (includes email form)
SAC Board Meetings are typically held at 10:00 a.m. on the 2nd Saturday of each month at Oakwood Cemetery. If you are interested in attending, please contact us to confirm time and place.
President: Sally Victor
Sally Victor started visiting cemeteries at a young age and enjoyed sharing the unique and decorative features with others in high school. She studied cemeteries professionally as a historic consultant during the 1980s in east Texas and marveled at the folklore and traditions exhibited. Sally has prepared several National Register nominations for historic cemeteries near Amarillo and San Antonio. She also does presentations on cemetery symbolism and cemetery walking tours. Sally has degrees from the University of Texas in American Studies and Community & Regional Planning with emphasis on Historic Preservation and History. The City of Austin cemeteries are really special and sincerely need better preservation.
Vice President: Melissa Rogers
Melissa has been fascinated with cemeteries since her childhood. She appreciates the unique historical perspective that cemeteries provide to a community. She has volunteered with SAC since 2016 as a member of the gravestone cleaning crew and as a tour guide for the MMM tours. Melissa is a Volunteer Docent at The Bullock Texas State History Museum where she specializes in the Comanche and early Native American trade routes with an emphasis on Jumano Trade Fairs. Melissa is committed to serving the community of Austin and is a Commissioner on the Municipal Civil Service Commission and a Volunteer Deputy Voter Registrar.
Secretary: Terri Hoover Mirka
Terri has been a SAC member since 2007 and leads SAC's marketing and gravestone cleaning projects. She holds a MBA degree in International Marketing and has retired from her most recent role as Marketing Director at Dell. Her first Texas ancestors were the Swisher family who moved to Robertson's Colony, Texas in 1833 and are buried at Oakwood. The Swishers were leaders in the Texas Revolution and the Republic of Texas and were also key figures in the development of Austin which they moved to in 1839. She is most interested in the rights of family owners at Oakwood, recognizing veterans, and headstone cleaning. Terri is also a member of several genealogical societies, Texas founders groups, and other local volunteer groups.
Treasurer and Historian: Kay Boyd
Kay has been a member of SAC since its inception. She is keenly interested in the preservation and care of Austin cemeteries. Her great-grandparents were Swedish immigrants who came to Austin and Texas in 1870 and are buried in Oakwood Cemetery. She also has family buried in the Oakwood Annex and Austin Memorial Park. Kay is also a member of the Austin Genealogical Society where she works with the Travis County cemetery project and county records. She was instrumental in beginning the Travis County Pioneer program. Besides cemeteries and genealogy, she is very interested in Travis County history.
Other Board of Director Members
Sally Baulch
Sally has worked in museums in the cultural history, education, and interpretation departments over the last thirty years. She currently works with Texas State Parks. Cemeteries were just another park to Sally and her siblings when she was growing up as they tagged along with the relatives and listened to stories. Her "home" cemetery is in Sweetwater, so she's adopted Austin's city cemeteries as her step-cemeteries. Outside of work, Sally also serves as a mentor at an elementary school, stewards her neighborhood park and her garden, and is a mother two grown children.
Karen Eshliman
Karen is a life long resident of Texas having grown up in Beaumont, TX where she attended Lamar University. She has been a resident of Austin for nearly a decade and has been a member of SAC since 2013. Karen is an Executive Assistant to a local entrepreneur and an Austin Tour Guide. Her love of Austin history lead her to SAC, leading cemetery tours and helping raise awareness of cemetery preservation. In addition to her involvement with SAC, Karen has been a volunteer for Keep Austin Beautiful since 2011, working as a Lake Leader in their project to keep Lady Bird Lake clean. Karen is also a volunteer at The Austin Visitors Center where she shares her knowledge of the city with visitors from all over the world.
Cynthia Evans
Cynthia, who was born and raised in Oklahoma, first became interested in family history as a young girl, listening to her great-grandmother talk about earlier times. As a young adult, her interest in genealogical research grew and she continues to document her family's history. Cynthia currently serves as the Genealogy Preservation Coordinator for the George Washington Carver Genealogy Center. She holds a B.A. in Business Administration and an M.A. in Museum Science. Since earning her Master's degree in 2004, she has worked extensively in various museums and archives in the state of the Texas, including the Lyndon B. Johnson National Historical Park in Johnson City, Texas and the Austin History Center, where she was honored to produce their first large exhibit on African American history in Travis County.
Lowell Herzog, Jr.
Lowell, a fifth generation Texan, is a cemetery headstone/monument conservator. He earned degrees in both History and English from Texas A&M University, and taught in public schools for over twenty years. Currently, he pursues stone conservation full-time throughout southeast Texas and has studied the various methods of conservation used in the U.S. and Europe for cemetery monuments and outdoor ironwork. Trained by nationally recognized gravestone and monument conservator Jon Appell, he is a member of the Association for Gravestone Studies (AGS) and the American Institute for Conservation of Historic and Artistic Works (AIC).
Scott Myers
Scott is a native Texan whose mother's ancestors were Swedish and settled in a small town on the Travis/Bastrop county line which they named after their home back in Sweden, Lund. Scott grew up in Austin and has held a variety of jobs and currently works for Weed Corley Fish Funeral Home – which he believes is "his calling." His grandparents are buried in Oakwood Annex, and his parents are buried in Austin Memorial Park. Scott has been an actor for SAC's tours for several years and has enjoyed the experience as well as the people he has met. He looks forward to helping SAC with its mission to Save Austin's Cemeteries.
Jan Root
Jan has been a great supporter of Save Austin's Cemeteries for many years, helping with special events, research, and planning. She is a native of Austin and a UT graduate with a BA in American History. Jan has extensive knowledge and experience in the archives field, working eighteen years at the Austin History Center, twelve years at the Harry Ransom Humanities Research Center, and two years as an archivist at Texas Parks & Wildlife. She also worked several years conducting historic surveys, including a US Navy project that took her to 37 states documenting Navy artifacts. She is currently a Certified Archivist at the Texas General Land Office, working with historic maps and land grants. Jan appreciates cemeteries for the link they provide to our past and the historic information that can be gathered from them. Jan is especially interested in SAC because of the work that's done to document and preserve Austin's cemeteries, thereby preserving her hometown's history.
Arro Smith
Arro Smith, PhD, is a librarian and historian. His research interests include public history, oral history methodology, and memory studies. He became interested in SAC while researching the Oakwood Cemetery plot belonging to his lodge of the Independent Order of Odd Fellows. The Odd Fellows take an oath to "Visit the sick, relieve the distressed, bury the dead, and educate the orphan." You will find many old graves with triple-link iconography or "F-L-T," representing the Odd Fellows' three links of Friendship--Love--Trust.
In Memory of Daniel Dwight Camacho (Nov 22, 1945 – April 27, 2016)
Danny was a long-time SAC board member, volunteer, gifted storyteller, avid researcher, champion of Mexicans & Mexican Americans in Central Texas and a dear friend to many.
© Save Austin's Cemeteries ~ All Rights Reserved
About SAC Events Home
Contact Us Volunteer FAQ
Join Us/Donate Shop Site Map


The Office of Juvenile Justice and Delinquency Prevention's (OJJDP's) toolkit to increase awareness about the prevalence of children's exposure to violence (CEV). The free, online resource includes an infographic and links to tip sheets, guides, and other publications on CEV.
On September 12, 2012, at 3:30 p.m., the center will host a 1-hour Twitter chat on CEV in school settings. Child advocates are encouraged to participate.
Access OJJDP publications on children's exposure to violence.
Learn about the Attorney General's Defending Childhood Initiative launched in 2010 to address children's exposure to violence.


text:
import "phoenix_html";
import "bootstrap";
import "bootstrap-select";

// Import local files
//
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"
$(document).off('click.bs.dropdown.data-api', '.dropdown form');

$(document).ready(function() {
    //initialize wizard
    var completeWizard = new wizard("#createServer");
    // Row Checkbox Selection
    $("input[type='checkbox']").change(function(e) {
        if ($(this).is(":checked")) {
            $(this).closest('.list-group-item').addClass("active");
        } else {
            $(this).closest('.list-group-item').removeClass("active");
        }
    });
    $('#lbSubmitButton').click(createLoadbalancer);
    $('.delete-domain').click(withAttr('domainId', (id) => {
        deleteDomain(id).then(() => {
            window.location.reload();
        }).catch((info) => {
            console.log(info);
            alert('Something went wrong! Please try again');
        });
    }));
    $('.approve-user').click(withAttr('userId', approveUser));
    $('.reject-user').click(withAttr('userId', rejectUser));
    $('.make-admin').click(withAttr('userId', makeUserAdmin));
    $('#editSave').click(withAttr('domainId',saveDomain));
    $('#flavor-input').on('change',(event) => {
        let data = event.target.selectedOptions[0].dataset;
        $('#flavor-detail-ram').text(humanFileSize(data.ram * 1000 * 1000,true));
        $('#flavor-detail-vcpus').text(data.vcpus);
    });
    $('#keypair-input').on('change',(event) => {
        let data = event.target.selectedOptions[0].dataset;
        $('#keypair-detail-fingerprint').text(data.fingerprint);
    });
    $('#public-input').on('change',(event) => {
        if(event.target.checked){
            $('#network-details').removeClass('hidden');
        } else {
            $('#network-details').addClass('hidden');
        }
    });
    $('#editModal').on('show.bs.modal',(event) => {
        let button = $(event.relatedTarget);
        let domain = button.data('domain');
        let username = button.data('username');
        let server_addr = button.data('server-addr');
        let id = button.data('id');
        var modal = $(this);
        modal.find('.modal-title').text('Edit domain: ' + domain);
        $('#editModal-host').val(server_addr);
        $('#editModal-domain').val(domain);
        $('#editModal-user').val(username);
        $('#editDelete').data('domainId',id);
        $('#editSave').data('domainId',id);
    });
    // deselect everything
    $('td input[type="checkbox"]').prop('checked',false);

    var table = $('#domain-table').DataTable({
        select: {
            selector: 'td:first-child input[type="checkbox"]',
            style: 'multi'
        },
        columns: [
            {name: "select",orderable: false},
            {name: "domain",orderable: true},
            {name: "user",orderable: true},
            {name: "server_addr",orderable: true},
            {name: "inserted_at",orderable: true},
            {name: "actions",orderable: false},
        ],
        order: [[1,'asc']]
    });
    $('#delete-selected').click(() => {
        toggleSpinner($('#delete-selected'));
        let selected = table.rows({selected: true}).data();
        let srv_ids = [];
        for(var i = 0; i < selected.length; i++) {
            srv_ids.push($(selected[i][5]).find('button').data().id);
        }
        let p = srv_ids.map((id) => {
            deleteDomain(id);
        });
        Promise.all(p).then(() => window.location.reload());
    });
    $('#selectAll').click(() => {
        $('.row-select').click();
    });
    $('.wizard-pf-complete button').click(() => window.location.replace('/'));
});

function withAttr(attr, fn) {
    return function(e) {
        var attrVal = $(e.target).data(attr);
        if (attrVal === undefined) {
            attrVal = $(e.target).parent().data(attr);
        }
        fn(attrVal);
    };
}

function humanFileSize(bytes, si) {
    var thresh = si ? 1000 : 1024;
    if(Math.abs(bytes) < thresh) {
        return bytes + ' B';
    }
    var units = si
        ? ['kB','MB','GB','TB','PB','EB','ZB','YB']
        : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
    var u = -1;
    do {
        bytes /= thresh;
        ++u;
    } while(Math.abs(bytes) >= thresh && u < units.length - 1);
    return bytes.toFixed(1)+' '+units[u];
}

function saveDomain(id) {
    let host = $('#editModal-host').val();
    let domain = $('#editModal-domain').val();
    $.ajax({
        url: `/api/domains/${id}`,
        type: 'PUT',
        data: {
            domain: {
                server_addr: host,
                domain: domain
            }
        }
    })
    .done(() => window.location.reload())
    .fail(() => alert('Failed!'));
}

function makeUserAdmin(id) {
    if (!confirm('Are you sure you want to make this user an Administrator?')) {
        return;
    }
    $.ajax({
            url: `/api/users/${id}`,
            type: 'PUT',
            data: {
                admin: true
            }
        })
        .done(() => window.location.reload())
        .fail(() => alert('Failed!'));
}

function rejectUser(id) {
    $.ajax({
            url: `/api/users/${id}`,
            type: 'PUT',
            data: {
                approved: false
            }
        })
        .done(() => window.location.reload())
        .fail(() => alert('Failed!'));
}

function approveUser(id) {
    $.ajax({
            url: `/api/users/${id}`,
            type: 'PUT',
            data: {
                approved: true
            }
        })
        .done(() => window.location.reload())
        .fail(() => alert('Failed!'));
}

function deleteDomain(id) {
    return new Promise((resolve,reject) => {
    $.ajax({
            url: `/api/domains/${id}`,
            type: 'DELETE'
        })
        .done(resolve)
        .fail(reject);
    });
}

function createLoadbalancer() {
    var subdomain = $('#textInput-modal-subdomain').val();
    var host = $('#textInput-modal-host').val();
    if (!$('#lbForm')[0].checkValidity()) {
        $('<input type="submit">').hide().appendTo($('#lbForm')).click().remove();
        return;
    }
    toggleSpinner($('#lbSubmitButton'));
    $.post('/api/domains', {
            domain: {
                domain: subdomain,
                server_addr: host
            }
        }).done(() => {
            window.location.reload();
        })
        .fail((data) => {
            toggleSpinner($('#lbSubmitButton'));
            var errors = data.responseJSON.errors;
            if (errors.domain) {
                setError($('#form-group-subdomain'), errors.domain[0]);
            }
            if (errors.server_addr) {
                setError($('#form-group-host'), errors.server_addr[0]);
            }
        });
}

function createServer(domain,flavorRef,imageRef,name,pub,keyName) {
    return new Promise((resolve) => {
            $.ajax({
            url: `/api/domains`,
            contentType: 'application/json',
            dataType: 'json',
            type: 'POST',
            data: JSON.stringify({
                domain: {
                    domain: domain
                },
                server: {
                    flavorRef: flavorRef,
                    imageRef: imageRef,
                    name: name,
                    key_name: keyName,
                    public: pub
                }
            })
        }).done(resolve);
    });
}

function setError(formgroup, error) {
    formgroup.addClass('has-error');
    formgroup.find('.help-block').removeClass('hidden').text(error);
}

function toggleSpinner(button) {
    button.find('.spinner').toggleClass('hidden');
    button.find('span').toggleClass('hidden');
}

var wizard = function(id) {
    var self = this,
        modal, tabs, tabCount, tabLast, currentGroup, currentTab, contents;
    self.id = id;

    $(self.id).click(function() {
        self.init(this);
    });

    this.init = function(button) {
        // get id of open modal
        self.modal = $(button).data("target");

        // open modal
        $(self.modal).modal('show');
        // adjust height of contents row (while steps and sidebar are hidden and loading message displays)
        self.updateWizardLayout();

        // assign data attribute to all tabs
        $(self.modal + " .wizard-pf-sidebar .list-group-item").each(function() {
            // set the first digit (i.e. n.0) equal to the index of the parent tab group
            // set the second digit (i.e. 0.n) equal to the index of the tab within the tab group
            $(this).attr("data-tab", ($(this).parent().index() + 1 + ($(this).index() / 10 + .1)));
        });
        // assign data attribute to all tabgroups
        $(self.modal + " .wizard-pf-sidebar .list-group").each(function() {
            // set the value equal to the index of the tab group
            $(this).attr("data-tabgroup", ($(this).index() + 1));
        });

        // create array of all tabs, using the data attribute, and determine the last tab
        self.tabs = $(self.modal + " .wizard-pf-sidebar .list-group-item").map(function() {
            return $(this).data("tab");
        });
        self.tabCount = self.tabs.length;
        self.tabSummary = self.tabs[self.tabCount - 2]; // second to last tab displays summary
        self.tabLast = self.tabs[self.tabCount - 1]; // last tab displays progress
        // set first tab group and tab as current tab
        // if someone wants to target a specific tab, that could be handled here
        self.currentGroup = 1;
        self.currentTab = 1.1;
        self.updateTabGroup();
        // hide loading message
        $(self.modal + " .wizard-pf-loading").addClass("hidden");
        // show tabs and tab groups
        $(self.modal + " .wizard-pf-steps").removeClass("hidden");
        $(self.modal + " .wizard-pf-sidebar").removeClass("hidden");
        // remove active class from all tabs
        $(self.modal + " .wizard-pf-sidebar .list-group-item.active").removeClass("active");
        // apply active class to new current tab and associated contents
        self.updateActiveTab();
        // adjust height of contents row (while steps and sidebar and tab contents are visible)
        self.updateWizardLayout();
        self.updateWizardFooterDisplay();

        //initialize click listeners
        self.tabGroupSelect();
        self.tabSelect();
        self.backBtnClicked();
        self.nextBtnClicked();
        self.finishBtnClick();
        self.cancelBtnClick();

        $(window).resize(function() {
            self.updateWizardLayout();
        });
    };

    // update which tab group is active
    this.updateTabGroup = function() {
        $(self.modal + " .wizard-pf-step.active").removeClass("active");
        $(self.modal + " .wizard-pf-step[data-tabgroup='" + self.currentGroup + "']").addClass("active");
        $(self.modal + " .wizard-pf-sidebar .list-group").addClass("hidden");
        $(self.modal + " .list-group[data-tabgroup='" + self.currentGroup + "']").removeClass("hidden");
    };

    // update which tab is active
    this.updateActiveTab = function() {
        if(self.currentTab == self.tabSummary){
            $('#review-name').text($('#name-input').val());
            $('#review-image').text($('#image-input option:selected').text());
            $('#review-flavor').text($('#flavor-input option:selected').text());
            $('#review-keypair').text($('#keypair-input option:selected').text());
            $('#review-networks').text($('#public-input')[0].checked);
            $('#review-subdomain').text($('#subdomain-input').val());
        }
        $(self.modal + " .list-group-item[data-tab='" + self.currentTab + "']").addClass("active");
        self.updateVisibleContents();
    };

    // update which contents are visible
    this.updateVisibleContents = function() {
        var tabIndex = ($.inArray(self.currentTab, self.tabs));
        // displaying contents associated with currentTab
        $(self.modal + " .wizard-pf-contents").addClass("hidden");
        $(self.modal + " .wizard-pf-contents:eq(" + tabIndex + ")").removeClass("hidden");
        // setting focus to first form field in active contents
        setTimeout(function() {
            $(".wizard-pf-contents:not(.hidden) form input, .wizard-pf-contents:not(.hidden) form textarea, .wizard-pf-contents:not(.hidden) form select").first().focus(); // this does not account for disabled or read-only inputs
        }, 100);
    };

    // update display state of Back button
    this.updateBackBtnDisplay = function() {
        if (self.currentTab == self.tabs[0]) {
            $(self.modal + " .wizard-pf-back").addClass("disabled");
        }
    };

    // update display state of next/finish button
    this.updateNextBtnDisplay = function() {
        if (self.currentTab == self.tabSummary) {
            $(self.modal + " .wizard-pf-next").addClass("hidden");
            $(self.modal + " .wizard-pf-finish").removeClass("hidden");
        } else {
            $(self.modal + " .wizard-pf-finish").addClass("hidden");
            $(self.modal + " .wizard-pf-next").removeClass("hidden");
        }
    };

    // update display state of buttons in the footer
    this.updateWizardFooterDisplay = function() {
        $(self.modal + " .wizard-pf-footer .disabled").removeClass("disabled");
        self.updateBackBtnDisplay();
        self.updateNextBtnDisplay();
    };

    // adjust layout of panels in wizard
    this.updateWizardLayout = function() {
        var top = ($(self.modal + " .modal-header").outerHeight() + $(self.modal + " .wizard-pf-steps").outerHeight()) + "px",
            bottom = $(self.modal + " .modal-footer").outerHeight() + "px",
            sidebarwidth = $(self.modal + " .wizard-pf-sidebar").outerWidth() + "px";
        $(self.modal + " .wizard-pf-row").css("top", top);
        $(self.modal + " .wizard-pf-row").css("bottom", bottom);
        $(self.modal + " .wizard-pf-main").css("margin-left", sidebarwidth);
    };

    // when the user clicks a step, then the tab group for that step is displayed
    this.tabGroupSelect = function() {
        $(self.modal + " .wizard-pf-step>a").click(function() {
            // remove active class active tabgroup and add active class to the
            // clicked tab group (but don't remove the active class from current tab)
            self.currentGroup = $(this).parent().data("tabgroup");
            self.updateTabGroup();
            // update value for currentTab -- if a tab is already marked as active
            // for the new tab group, use that, otherwise set it to the first tab
            // in the tab group
            self.currentTab = $(self.modal + " .list-group[data-tabgroup='" + self.currentGroup + "'] .list-group-item.active").data("tab");
            if (self.currentTab == undefined) {
                self.currentTab = $(self.modal + " .list-group[data-tabgroup='" + self.currentGroup + "'] .list-group-item:first-child").data("tab");
                // apply active class to new current tab and associated contents
                self.updateActiveTab();
            } else {
                // use already active tab and just update contents
                self.updateVisibleContents();
            }
            // show/hide/disable/enable buttons if needed
            self.updateWizardFooterDisplay();
        });
    };

    // when the user clicks a tab, then the tab contents are displayed
    this.tabSelect = function() {
        $(self.modal + " .wizard-pf-sidebar .list-group-item>a").click(function() {
            // update value of currentTab to new active tab
            self.currentTab = $(this).parent().data("tab");
            // remove active class from active tab in current active tab group (i.e.
            // don't remove the class from tabs in other groups)
            $(self.modal + " .list-group[data-tabgroup='" + self.currentGroup + "'] .list-group-item.active").removeClass("active");
            // add active class to the clicked tab and the associated contents
            $(this).parent().addClass("active");
            self.updateVisibleContents();
            if (self.currentTab == self.tabLast) {
                $(self.modal + " .wizard-pf-next").addClass("hidden");
                $(self.modal + " .wizard-pf-finish").removeClass("hidden");
                self.finish();
            } else {
                // show/hide/disable/enable buttons if needed
                self.updateWizardFooterDisplay();
            }
        });
    };

    // Back button clicked
    this.backBtnClicked = function() {
        $(self.modal + " .wizard-pf-back").click(function() {
            // if not the first page
            if (self.currentTab != self.tabs[0]) {
                // go back a page (i.e. -1)
                self.wizardPaging(-1);
                // show/hide/disable/enable buttons if needed
                self.updateWizardFooterDisplay();
            }
        });
    };

    // Next button clicked
    this.nextBtnClicked = function() {
        $(self.modal + " .wizard-pf-next").click(function() {
            // go forward a page (i.e. +1)
            self.wizardPaging(1);
            // show/hide/disable/enable buttons if needed
            self.updateWizardFooterDisplay();
        });
    };

    // Finish button clicked
    // Deploy/Finish button would only display during the second to last step.
    this.finishBtnClick = function() {
        $(self.modal + " .wizard-pf-finish").click(function() {
            self.wizardPaging(1);
            self.finish();
        });
    };

    // Cancel/Close button clicked
    this.cancelBtnClick = function() {
        $(self.modal + " .wizard-pf-dismiss").click(function() {
            // close the modal
            $(self.modal).modal('hide');
            // drop click event listeners
            $(self.modal + " .wizard-pf-step>a").off("click");
            $(self.modal + " .wizard-pf-sidebar .list-group-item>a").off("click");
            $(self.modal + " .wizard-pf-back").off("click");
            $(self.modal + " .wizard-pf-next").off("click");
            $(self.modal + " .wizard-pf-finish").off("click");
            $(self.modal + " .wizard-pf-dismiss").off("click");
            // reset final step
            $(self.modal + " .wizard-pf-process").removeClass("hidden");
            $(self.modal + " .wizard-pf-complete").addClass("hidden");
            // reset loading message
            $(self.modal + " .wizard-pf-contents").addClass("hidden");
            $(self.modal + " .wizard-pf-loading").removeClass("hidden");
            // remove tabs and tab groups
            $(self.modal + " .wizard-pf-steps").addClass("hidden");
            $(self.modal + " .wizard-pf-sidebar").addClass("hidden");
            // reset buttons in final step
            $(self.modal + " .wizard-pf-close").addClass("hidden");
            $(self.modal + " .wizard-pf-cancel").removeClass("hidden");
        });
    };

    // when the user clicks Next/Back, then the next/previous tab and contents display
    this.wizardPaging = function(direction) {
        // get n.n value of next tab using the index of next tab in tabs array
        var tabIndex = ($.inArray(self.currentTab, self.tabs)) + direction;
        var newTab = self.tabs[tabIndex];
        // add/remove active class from current tab group
        // included math.round to trim off extra .000000000002 that was getting added
        if (newTab != Math.round(10 * (direction * .1 + self.currentTab)) / 10) {
            // this statement is true when the next tab is in the next tab group
            // if next tab is in next tab group (e.g. next tab data-tab value is
            // not equal to current tab +.1) then apply active class to next
            // tab group and step, and update the value for var currentGroup +/-1
            self.currentGroup = self.currentGroup + direction;
            self.updateTabGroup();
        }
        self.currentTab = newTab;
        // remove active class from active tab in current tab group
        $(self.modal + " .list-group[data-tabgroup='" + self.currentGroup + "'] .list-group-item.active").removeClass("active");
        // apply active class to new current tab and associated contents
        self.updateActiveTab();
    };

    // This code keeps the same contents div active, but switches out what
    // contents display in that div (i.e. replaces process message with
    // success message).
    this.finish = function() {
        $(self.modal + " .wizard-pf-back").addClass("disabled"); // if Back remains enabled during this step, then the Close button needs to be removed when the user clicks Back
        $(self.modal + " .wizard-pf-finish").addClass("disabled");

        let name = $('#name-input').val();
        let image = $('#image-input').val();
        let flavor = $('#flavor-input').val();
        let keypair = $('#keypair-input').val();
        let domain = $('#subdomain-input').val();
        let keyName = $('#keypair-input').val();
        let pub = $('#public-input')[0].checked;
        if(keyName === 'None'){
            keyName = undefined;
        }

        createServer(domain,flavor,image,name,pub,keyName).then(() => {
            $(self.modal + " .wizard-pf-cancel").addClass("hidden");
            $(self.modal + " .wizard-pf-finish").addClass("hidden");
            $(self.modal + " .wizard-pf-close").removeClass("hidden");
            $(self.modal + " .wizard-pf-process").addClass("hidden");
            $(self.modal + " .wizard-pf-complete").removeClass("hidden");
        });
    };

};

redpajama_set_name: RedPajamaGithub


text:
Home News Solving the puzzle
Solving the puzzle
June 20, 2008, 2:39 p.m. (ET)
On June 11, the International Volleyball Federation (FIVB) announced the schedule for the preliminary matches of the Olympic indoor volleyball tournament. The U.S. women are in pool A, and their first match will be held August 9 against 29th-ranked Venezuela.
The U.S. women are currently ranked fourth in the world.
U.S. head coach Jenny Lang Ping would not comment on any of the 11 other women's volleyball teams that have qualified for the 2008 Olympics. But a match against a team ranked far down in the standings should help the U.S. gain confidence as the Olympics begin.
At the Pan Am Cup in early June, the U.S. national team's youngest players beat Venezuela in a five-game match. With seasoned veterans likely to make the U.S. Olympic volleyball team, the U.S. will likely beat Venezuela more decisively in Beijing.
But with less than two months to go before the first Olympic match, Lang Ping has yet to determine which veterans and which young players will comprise the 12-woman Olympic team.
Although many of the younger players have trained with Lang Ping at the Olympic Training Center in Colorado Springs this spring, 15 members of the women's national team played overseas in pro leagues throughout the fall and winter. Most didn't return home until mid-May.
"The first time we had the full team was Monday (June 9)," Lang Ping said after the first of a three-match exhibition tournament with Brazil, held June 11 at OTC in Colorado Springs. Brazil is currently the top ranked team in the world.
Lang Ping and her staff are using the three-match exhibition tournament, plus the World Grand Prix, held over three consecutive weekends from June 20 until July 6 in Asia and Europe (with the finals slated for July l8-13, if the U.S. qualifies), to pick 12 players from a group of at least 16 talented athletes to go to Beijing.
Eight are Olympic veterans. Logan Tom, who was key in helping the U.S. finish third in the World Cup in November 2007, which qualified the U.S. for the Olympics, has returned to the national team after playing professionally overseas and on the beach for the U.S. for the past three years. She competed in the 2000 and 2004 Olympics, where the U.S. finished fourth and fifth, respectively.
The U.S. women have not medaled in indoor volleyball since 1992.
Also aiming for a third Olympics are Stacy Sykora, the team's libero who earned the best digger award at the 2000 Olympics; Heather Bown, an all-around player who finished second on her team at the 2000 Olympics in blocks, serving aces, and hitting percentage; and Robyn Ah Mow-Santos, named most valuable player in her European pro league last season.
(A libero specializes in defense and serve reception. She wears a contrasting uniform and can replace any back-row player throughout a match without counting as a substitution.)
Striving to make their second Olympic team are starting setter Lindsey Berg, Tayyiba Haneef-Park, who helped the U.S. score the bronze at the 2007 World Cup, and Ogonna Nnamani, a reserve on the 2004 Olympic team. A three-time All-American high jumper at Long Beach State College who is 6'7" tall, Haneef-Park also competed in the 2000 U.S. Olympic Track and Field Trials, finishing tenth.
Danielle Scott-Arruda has her eye on a fourth trip to the Games.
Younger players vying for the Olympic team are Stanford University star Cynthia Barboza, who scored the second highest number of kills (11) in the first exhibition match against Brazil, and Kristin Richards, a Stanford grad who holds the school's record for career digs (1,597).
Coach Lang Ping says she is not looking necessarily for the most powerful players to take to Beijing (the former Chinese volleyball star's hometown).
"We are trying to solve this big puzzle and see which area of the game is more important to make up for areas we lack," Lang Ping has said. "For example, we may have players that are not as strong at the net, but they are great in the back row. It doesn't mean we have to bring the best hitters as we need balance as well."
"I have a feeling we have 16 players to fight for the 12 spots on the Olympic roster," she adds. "For a few positions, we will probably make a last minute decision. Before going to China, we will have four or five days training in California with 14 or 15 players in case of injuries and make our last minute decisions there if needed."
Although some will no doubt be frustrated when their names do not appear on the Olympic roster, the women and their coach say it's a positive competition for the 12 spots.
"Everybody tries to compete, tries to play better," Lang Ping says. "You make your teammates better, not the other way around. We take 12. It doesn't mean that the others are not good. It just depends on what the team needs. The others are great players who push the team."
When asked if she is confident about making the Olympic squad, Barboza says she isn't really focusing on it. "At this point, I'm just trying to get better. That's all I can really focus on. I'm just trying to learn from the teammates around me and make a push for that spot."
No matter which 12 are selected, the challenge is learning to play with each other to improve ball connections, says Lang Ping. In the U.S.-Brazil exhibition matches in mid-June, Brazil won two out of three.
When asked what puts Brazil on the top, Lang Ping says, "(They have) very good ball control, and they play really fast from the back row. It's hard to find a weakness. That's why they are number one."
In addition to playing Venezuela at the Olympics, the U.S. will also compete against China, Cuba, Japan, and Poland in pool A. In third, Cuba is the only team ranked higher than the U.S. in pool A. China is ranked sixth, Japan eighth, Poland ninth, and Venezuela 29th.
Brazil and number-two-ranked Italy are in pool B.
"All the teams who have qualified for the Olympic Games are pretty good," Lang Ping says. "You have to play perfect or your opponent can knock you off. I would think six to eight teams have a good opportunity to medal at the Olympic Games. Also, it will take a little bit of luck for teams as the crossover from the pool play into the quarterfinal match-up will play a role on who advances into the medal round."
Peggy Shinn is a freelance contributor for teamusa.org. This story was not subject to the approval of the United States Olympic Committee or any National Governing Bodies.