text:
11 Emerging Artists to Look Out for in 2023
From Dylan Sinclair and Pip Millett to notfortheo, CJ Flemings, and more.
by Stella He & Gabby Sgherri
Publishing date: Jan, 11, 2023
It's 2023 and whether you subscribe to the whole "new year, new me" ideology, the calendar reset marks the slate clean for you to measure whatever you please—resolutions, relationships, personal goals…etc. For the musically inclined, this means a new year of releases and opportunities for burgeoning artists to rise from the crevices of Spotify and Apple Music's catalog depths and make their way into conversations with your not-so-musically inclined friends. So in the spirit of out with the old and in with the new, we rounded up 11 artists destined to have a great year and deserving of a spot on your music queue. If you're an R&B stan, then Toronto native Dylan Sinclair will satisfy your refined palette. If you're looking for alternative chillwave sounds that make you stop your study session and double-take the song that's playing, look no further than notfortheo. As genres become increasingly outdated, and many artists we've highlighted straddle more than one, we assure you you'll find artists whose music is as sonically soothing as it is lyrically stimulating.
After breaking out with the self-released, deeply personal album, Proverb, in 2020, the Filipino-Guyanese singer, Dylan Sinclair, found himself with a JUNO nomination for Traditional R&B/Soul Record of the Year and a glimpse of what's to come. The gospel-influenced EP has remnants of Sinclair's beginnings, he grew up singing in the church choir and was inspired by the work of Gospel singer, Fred Hammond and his musical group, Commissioned. Sinclair equally credits the contemporary work of Frank Ocean and Daniel Caesar for instilling hope that he could see success in an alternative R&B lane. As his musical talent and ambition expanded, the 20-year-old outgrew his hometown of Thornhill, Ontario, and decided to move into the city of Toronto. The shift in his environment resulted in his newest album, No Longer in the Suburbs, where he details the freedoms, temptations, and torments that come on the cusp of fame in a city full of distractions. Instrumented by soulful, meditative R&B tracks, Dylan works through moral trials as he enters adulthood and tensions between familiar and foreign. Now with millions of streams under his belt, he earns the title of Toronto's next R&B sensation, and it is only a matter of time before this one-of-a-kind talent takes it to the global stage.
Cool, calm, and collected is how you will feel listening to the hallucinatory psychedelic sounds of Chiiild. With extensive experience in producing and co-writing, think Jennifer Lopez, Chole x Halle, and Usher, Chiiild developed his distinct rhythm and otherworldly auditory aesthetics that make him one to watch. Coined "synthetic soul," Chiiild weaves modern R&B, psychedelia, and smooth retro soul to pioneer a pinging listening experience that consummates the likes of D'Angelo, Tame Impala, and Marvin Gaye. But it doesn't stop there; the singer speaks harsh truths about life, love, and social justice in his lyricism, elevating his work beyond sound. Listen to "Pirouette," "Count Me Out," and "Sleepwalking" and see if the ghostly calming vocals overtopping electronically funk-ridden beats don't soothe your inner turmoil. His use of striking synths and water guitar riffs also reminds us of the soulful and calming undertone we could all take into the new year ahead.
BRB, currently crying to Reneé Rapp's debut EP, Everything to Everyone. If the name sounds familiar, Rapp starred in Broadway's Mean Girls as Regina George and currently stars in HBO Max's The Sex Lives of College Girls as Leighton Murray. After years of portraying fictional characters and subsequently telling their stories, Rapp is ready to write her own as a singer-songwriter. Her debut EP brims with self-reflection, proving she has something to say. Depicting her roles beyond the screen, the up-and-comer recalls moments in her personal life: as a lover, daughter, and trusted confidante. The record comprises seven R&B cuts and pop ballads, each emotionally charged yet addictively melodic. Her songs are for anyone who needs to cry over some truths from failed relationships and growing pains à la Olivia Rodrigo. Currently in our Reneé Rapp era, and we can't wait to see what Rapp has to unwrap for us in the rest of 2023.
Montréal native, CJ Flemings, has become known as the soft-spoken prince because of his ability to spit smooth bars and tight flows over post-trap drums and pop-inflected hip-hop beats. Having started his career in his early teens, he became accustomed to mixing and mastering his projects alone which refined his ability to know exactly what he wants when working with other creatives. JUNO award-winning hip-hop producer, Michael Lantz, produced his second album, Mascara Tears, resulting in a polished offering of melodic flows, poignant lyricism, and earworm beats. He explores universal themes of romantic turmoil, existentialist doubts, and benevolence vs ego. He displays versatility on recent singles like "Feelings In A Tuck", which favors a bouncy and melodic rap flow, and "Dirty Sprite Toast Freestyle" where he spits classic hip-hop bars. We can only hope 2023 is the year CJ Flemings expands his existing universe and lets us take a trip inside his melodic mind.
If you ever need to get out of the city for a breath of fresh air, notfortheo's got your back. Releasing their debut EP half-life, towards the end of last year, the sizzling four-track record is a dynamic offering with wavy synth chord progressions and laid-back vocals. The group's unique musicality strikes an unlikely balance between nostalgia and catharsis. Adding on top of that, top-noting drums and fat baselines, notfortheo creates soundscapes that transcend listeners to otherwordly dimensions and pluck them out of their everyday life. Although notfortheo entered the chillwave space like a hot new bombshell, the group's members are veterans who have long been experimenting in the Toronto production scene. The amalgamation of each member's experience can be heard in the cohesiveness of the EP, along with the sonic experimentation fusing indie-pop, alternative, rap, and chillwave together. This genre-bending powerhouse is a group to keep an eye on in 2023, and unlike what their name suggests, notfortheo's music is for everyone.
Lous and the Yakuza is the embodiment of duality, and we're all here for it. Not wanting to settle for any specific genre, the Conglonese-Belgian artist combined trap, pop, and skittering R&B in her debut album Gore, and curated her personal style—melding the avant-gardeness of Margiela with the casualness of Adidas. Lous thrives on delivering the totally unexpected, take her stage name for example. "Lous" is an anagram for "Soul" and "Yakuza" is the Japanese word for "loser." In a recent interview, she said the inception of her name, "speaks to my sense of resilience […] and my love for those who don't conform." Her experimentalist mentality led to her song "Dilemme" racking up more than 10 million streams. Subsequently, she was tapped by the fashion house, Louis Vuitton, to become one of their modeling muses. Honing in on her Congolese rumba rhythms and making space for her playful and "dreamy" side, she returns with her second full-length release, IOTA. The singer's gutsy nature destines her to be defiant of norms, and she's not stopping until her Lous universe is fully formed.
If you need a sign to listen to Preston Pablo, here it is. Riding off the success of his platinum-selling single "Flowers Need Rain," which currently has over 46 million global streams, Preston closed out 2022 with the single "Love You Bad" showcasing his genre-crossing ability. Since his debut, he's honed his "modern vintage style", which draws on elements of pop and R&B elevated by his own unique twist. Its small-town roots meet the big stage with Preston starting off most songs from the classical side, using a guitar or piano, and figuring out how to evolve it from there. He's already released his first single of 2023 titled "AY AY AY". Merging dance-floor sounds with pop energy, he says, "this song is the fantasized world built around my wildest desires. It's my materialistic idea of success being manifested through a song." You can always count on Preston to deliver honest lyrics and dynamic melodies with lots more music to come this year.
Ogi has been on our radar for a minute. Her performance of her debut single, "I Got It," at the 2022 BET Awards ratified her artistry as a force to be reckoned with. Her debut album, Monologues, is a smooth and sultry record that showcases her unique sound capabilities—bolstered by her grammy-winning production partner, No. I.D. Ogi has cultivated her own brand of music through her confessional truths, uncompromising range, and composition. Melancholy drips atop tracks like "Envy" and "Let Me Go" while grounding bass drums and crisp falsetto juxtaposes jazzy warmth with harmonizing hummings. Full of melodic laughs and sonic explorations, Monologues lays the perfect foundation for the rising star to work its way into the ranks of other modern rhythms and blues stars, and to say we're excited is an understatement.
It's 2023, and Pip Millett is reminding us to stop accepting the bare minimum. When Everything Is Better, I'll Let You Know was released in late October, the singer's no-nonsense attitude offered a firm reminder to shun our fears and embrace independence, ownership, and boundaries to things that no longer serve us. Baring it all in the effort of self-discovery and honesty, Pip brings her listeners along on her journey and does so over jazzy trumpets with dreamy, ethereal grooves. Her personal growth and embrace of womanhood are glaring in her raw lyricism, and they seem to be what we didn't know we needed to hear. Like in "Smoking," where she sings, "This love is broken, it's broken / I didn't want to let you go / Couldn't see the light / I was in the dark." And in "Walk Away," where she sings, "My love is not a favor / I'm doing way too much / That's why I have to cut you off." Consider her songs as advice from a wise friend telling you to move on when things aren't working out. Pip Millett, everyone, is the up-and-comer for our independent girlie anthems.
"Rebel with a cause," also known as Crash Adams, is making us rock out with their latest single, "Caroline." Brewing their talent in Toronto's creative scene, the duo made its debut in 2019 and has been an unstoppable force since pumping out lighthearted, feel-good music for their fans and listeners worldwide. Despite making quite a commotion on social media, they remain rooted in Toronto and give homage to the city's landmarks like the bustling Yonge and Dundas intersection and the bulk-buying store Bulk Barn, both in their music videos and EP covers. Through scintillating guitar riffs and uplifting drum rumbles, Crash Adams make a name for themselves as a group that doesn't take themselves too seriously and the maker of bangers one after another.
TikTok sensation Sofia Camara devotes her music to relatability, above all else, offering up her experience so others can better understand theirs. At just 20 years old, her two singles, "Without You" and "Never Be Yours," garnered more than 6.1 million likes on TikTok. In today's world, virality tends to be the earliest markings of an up-and-coming star. Touching on universal themes of heartache and infatuation, Sofia gives her unique perspective which is a perfect mix of post-adolescent curiosity and a maturity that is wise beyond her years. A radio-ready pop ballad with a crunchy touch of electro-pop-inspired rock, the Toronto-raised Portugal native lays her mind bare for her listeners, and it's only a matter of time before becoming the next breakout hit.


text:
To all the world...
"Go into all the world and preach the good news to all creation." (Mark 16:15, NIV)
Swe-e-e-t !!!
One of the peculiar joys of living in Wisconsin was the number of radio stations that would suspend their regular programs or music playlists at some point in November (sometimes around Thanksgiving, sometimes as early as Veterans Day) and play Christmas music 24 hours a day until Christmas was over. I know that to some of you the idea may sound awful. I thought so too, at first; but then the "Advent discipline," as I came to think of it, took hold, and now I really miss hearing Christmas music—be it carols, anthems, or jazz and rock oldies—for four to six weeks out of every year. (I also developed a serious addiction to cheese of all kinds during those same wonderful years—a habit I ain't kicking, ever!)
So I was really gratified to read Todd Starnes' column on Fox News this week, celebrating the fact that that a Madison, Wisconsin radio station, Liberal Talk "92.1 The Mic" will now be called "92.1 Best FM" — "Madison's Home for the Holidays." What made the news really sweet was that the station being taken over will no longer be hosting the radio program of the Freedom From Religion Foundation—Wisconsin's answer to Madalyn Murray O'Hair. I'll let Todd Starnes tell you the rest:
Radio station dumps atheists for Christmas music
The Freedom From Religion Foundation, a motley crew of atheists, agnostics and free-thinkers just got a lump of coal in their Christmas stockings.
WXXM, the progressive talk radio station in Madison, Wisconsin, has flipped formats – leaving the uber-liberal city without a place to converse about micro-aggressions, plot protest marches or swap quinoa recipes.
The Wisconsin State Journal reports that Liberal Talk "92.1 The Mic" will now be called "92.1 BestFM" -- "Madison's Home for the Holidays."
Yes, good readers -- progressive talk was replaced with around-the-clock Christmas music. Ho! Ho! Ho!
Among the shows given the heave-ho as a result of the format change was "Forethought Radio," a show hosted by the Freedom From Religion Foundation.
"We opened up the Wisconsin State Journal the morning after the election to read the remarkable announcement that progressive talk had been banished forthwith on 92.1 FM and replaced with around-the-clock Christmas music," FFRF co-founder Annie Gaylor said in a statement.
Well, if that doesn't curdle an atheist's egg-nog I don't know what will.
"It's not exactly the appropriate vehicle for Freethought Radio now," Ms. Gaylor lamented.
The Freedom From Religion Foundation is not a big fan of the Baby Jesus.
They make their living by filing lawsuits against towns that display the Nativity Scene and by bullying schools that sing Christmas carols.
They're basically a bunch of godless Grinches – pillaging and plundering their way through the yuletide season.
In 2015 the FFRF filed a federal lawsuit against an Indiana school district –demanding the little Lord Jesus be evicted from a Christmas pageant.
That same year, they were successful in banning public school choirs in Portland, Oregon from performing at a Catholic shrine called the Grotto.
They also tried to bully the good people of Piedmont, Alabama for making "Keep Christ in Christmas" the theme of the annual holiday parade.
But the FFRF's devious scheme was foiled by some mighty clever thinking. Instead of making it the "official" theme – the town decided to make it the "unofficial" theme.
Radio Insight reports the station's flip to Christmas music will lead to a new format after the holidays. It's unclear what that format will be – but it's unlikely liberal talk will return to the airwaves.
Christian Examiner reports the station's programming was being trounced in the ratings by conservative talk radio giants like Rush Limbaugh and Sean Hannity (a great American and my colleague at Fox News).
Let's be honest – would you rather listen to Rush and Sean or a gaggle of man-hating feminists in Birkenstocks warbling about the virtues of organic gardening.
Progressive talk radio does not make for good talk radio and that's why WXXM opted to play Jingle Bells instead of blathering atheists.
Now that the Freedom From Religion Foundation has been silenced, the citizens of Madison will finally be able to enjoy the holiday season with peace on Earth – goodwill to men.
Christmas really is the most wonderful time of the year!
Todd Starnes is host of Fox News & Commentary, heard on hundreds of radio stations. His latest book is "God Less America: Real Stories From the Front Lines of the Attack on Traditional Values." Follow Todd on Twitter @ToddStarnes and find him on Facebook.
Here again is the link to Todd Starnes' column on Fox News.
Posted by Robert S. Munday at 3:00 AM
Robert S. Munday
Our lives begin to end
the day we become silent
Fidel Castro Dead: Nothing Changes
Study Finds that Mainline Protestant Churches that...
Feeling the spirit of '76 in 2016
America Wins!!!
Max Lucado: My prediction for November 9
Anglican Curmudgeon
Anglican Essentials
Anglican Frontier Missions
Anglican Ink
Anglican Library
Anglican Revivalist
Anglican Update
BabyBlueOnline
Biblia Sacra Design
Billy Ockham
Break Point
Christian Post
Desiring God (John Piper)
Ekklesia Society
Free Range Anglican
Get Religion
Global South Anglican
Hot Rod Anglican
Incline Your Heart
Nashotah House
Omega Society
San Diego Anglicans
Sharing of Ministries Abroad (SOMA)
South American Missionary Society
Stephen's Witness
Techno-cality
Trinity School for Ministry
Uganda Partners

redpajama_set_name: RedPajamaCommonCrawl


text:
Browse By Topic (61)
Pacific, The Lost Evidence: Saipan (2005)
Watch Documentary
Watch Part Number:
Full Documentary
Date Added: 10 years ago.
Documentary Description
A week after D-Day and half a world away, American forces faced Japanese ground forces for the first time.
A cutting-edge combination of CGI animation and aerial footage.
As each moment unfolds, experts analyze the tactics and strategies.
Each episode offers an unforgettable profile of a pivotal engagement.
The footage sat for decades, its unique view of important encounters unseen. Shot from aircraft high above the Pacific, it captures the intense action as American forces battled Japanese defenders in the fabled "Island-Hopping" campaign that led to Japan's doorstep.
Enriched with cutting-edge CGI graphics which create detailed contour maps of the islands, PACIFIC: THE LOST EVIDENCE sheds new light on some of WWII's most important engagements.
Just over a week after the D-Day, on the other side of the world, 70,000 U.S. Marines stormed ashore on the Pacific island of Saipan. For the first time in the war, American fighting men stood on Japanese soil. Facing them were 30,000 Japanese soldiers, with massed tanks and artillery, determined to defend the island to the death.
PACIFIC: THE LOST EVIDENCE offers extraordinary insight into this climactic battle while following the men of the invasion force as they fought their way to ultimate victory--despite of one of the biggest Banzai charges of WWII.
Related Documentaries
People who watch this documentary also look for:
Secrets of the Dead: Japanese SuperSub (2010) 8,154 views
Armenia: The Betrayed (2003) 4,570 views
Oracle of Delphi Secrets Revealed (2003) 10,491 views
China: The Roots of Madness (1967) 6,591 views
From D-day to the Dam (1944) 8,903 views
Nubia: The Forgotten Kingdom (2003) 10,672 views
The Soviet Story (2008) 10,359 views
Churchill's Island (1941) 6,685 views
What the Ancients Did for Us: The Indians (2005) 8,584 views
Quest for the Lost Civilization (1998) 9,396 views
All external videos in CosmoLearning are merely links to outside video hosts that make available embed codes to be used by external websites or blogs. CosmoLearning will never be responsible for any kind of hosting of external productions. To contact the original host company or uploader, please click on the video displayed to be forwarded to the original video.


picture on resume good or bad of a cover letter awesome collection.
good picture resume of a great resumes samples sample here are.
picture on resume good or bad of a how to make unique pretty decent.
good picture resume of a step 3.
good picture resume of a pr.
picture on resume good or bad of a characteristics essay rainbow 2 going.
good picture resume of a excellent examples example objective statement best my perfect.
good picture resume of a.
good picture resume of a the best copy image.
picture on resume good or bad of a example with no experience.
picture on resume good or bad of a example with no experience objectives for sales.
picture on resume good or bad of a whats objective for super idea best 4 ideas.
good picture resume of a copy resumes.
good picture resume of a how to make job samples.
good picture resume of a proper format free builder 5.
picture on resume good or bad of a tips for resumes.
picture on resume good or bad of a how to create best ideas about example in an.
good picture resume of a sample example layout.
picture on resume good or bad of a instance superb.
good picture resume of a summary examples example well objective on necessary.
picture on resume good or bad of a examples example doc sample.
picture on resume good or bad of a format download write the best for fresher teachers.
picture on resume good or bad of a and examples example resumes best cov.
picture on resume good or bad of a.
picture on resume good or bad of a an example how to write proper popular examples.
good picture resume of a writing.
good picture resume of a example examples resumes first job template for.
picture on resume good or bad of a for teacher job elegant inspirational new sample best cover luxury formatted.


Intel Corp said on Tuesday it was exiting the 5G smartphone modem business, while assessing opportunities for 4G and 5G modems in PCs, internet of things devices and other data-centric devices.
REUTERS: Intel Corp said on Tuesday it was exiting the 5G smartphone modem business, while assessing opportunities for 4G and 5G modems in PCs, internet of things devices and other data-centric devices.
"...in the smartphone modem business it has become apparent that there is no clear path to profitability and positive returns," Intel CEO Bob Swan said in a statement.


text:
Vera Johnson, herself
Vera Johnson (1920-2007), a 52-year old native Canadian folk singer (at the time of this recording), sings with her masterful lyrics about her life, politics, and the women's movement. Vera came to Houston in February 1973 to sing for the National Women's Political Caucus, which was hosting their first convention, in Houston, Texas from February 9-11, 1973. Produced by Marie Blazek for KPFT. This program contains sensitive material. Some problems with recording levels.
Original tape box image:
KPFT
KPFT, 13 March 1973
Folk-songs.
Johnson, Vera
National Women's Political Caucus (U.S.)
Women folk musicians
Marie Blazek
American Women -- Music and musicians
Los Angeles : Pacifica Radio Archives, 1973
View Folio here (at Archive.org):
KPFT Folio, March 1973
This recording has been digitally preserved as part of Pacifica's American Women Making History and Culture: 1963-1982 grant preservation project, and is available for research and reference . Please contact the archives via telephone: 818-506-1077 or email: americanwomen at pacificaradioarchives dot org for information on how to obtain a copy of this program. Thank you.


text:
Q: Skip lines without commas I have a huge csv file and I want to import it to R for some analysis. Some of the lines inside the csv doesnt have any commas and need to be discarded.
How can R reads csv line by line and skip those lines?
As an example, here is list
id,length,height
1,70,50
2,82,40
3,64,30
these lines
should be discarded
4,48,22
5,32,14

my desired imported data in R:
id,length,height
1,70,50
2,82,40
3,64,30
4,48,22
5,32,14

Edit: I applogize that I didnt send a good example. How can we improve the answer for this data.I need an answer that can detect lines without comma not an answer that detects lines without number.
id,length,height
1,70,50
2,82,40
3,64,30
rsammsa='b'
sdasdsa='a'
sadas='021210'
@sss
4,48,22
5,32,14

with desired output as before

A: We can read the data using readLines and then remove the lines that has all non-numeric characters along with space from first (^) to last ($) using grep.  Read the subset of lines with read.table/read.csv
lines <- readLines("yourfile.txt")
lines1 <- lines[!grepl("^[A-Za-z ]+$", lines)]
dat <- read.table(text=lines1, sep=",",
             header=TRUE, stringsAsFactors=FALSE)
dat
#   id length height
#1  1     70     50
#2  2     82     40
#3  3     64     30
#4  4     48     22
#5  5     32     14

Update
Based on the new data showed by the OP, we can modify the grep
lines1 <- lines[c(TRUE,!grepl('[^0-9,]', lines[-1]))]

and then read as before
dat <- read.table(text=lines1, sep=",",
         header=TRUE, stringsAsFactors=FALSE)
dat
#   id length height
#1  1     70     50
#2  2     82     40
#3  3     64     30
#4  4     48     22
#5  5     32     14

redpajama_set_name: RedPajamaStackExchange


TOPIC: Random Glitch happening in certain games?
I have had this issue in multiple games but most recently in Fallout 76. I have ReShade running and press the hotkeys to open the GUI and I can't move the mouse over the ReShade GUI... Its like bouncing my cursor off of something and won't allow me to get over to the check-boxes or tabs!
That also happens in Fallout 4. One way to fix it (at least in FO4) is to temporarily connect a controller. That disables the keyboard/mouse input and you can move the cursor freely when the GUI is open. No idea if that works in Fallout 76 though (probably, because creation engine...).
I really would like a GOOD FIX for this!
Hard to change settings in-game if you can't get to the settings!
Bring up the main menu in the game first, then bring up the Reshade interface.
This technique works with The Long Dark, XCom2 and Fallout 4 (last time I loaded it).


text:
The argument about Guitar Hero that I never want to hear again, part one
If you're interested in certain controversial subjects, you tend to run across the same facile arguments over and over. Among these are:
Communism works great -- in theory.
Religion is the cause of every major war in human history.
Evolution is a theory, not a fact.
All of which are shorthand for: "I don't understand what I'm talking about, and have no real desire to find out, yet I suffer from an uncontrollable compulsion to express an opinion about things." Here's another one I'd like to throw onto the pile:
Instead of playing Guitar Hero/Rock Band, you should learn to play a real instrument.
This more often expressed as a question: "Why don't you learn to play a real instrument?"
Well, why don't we learn to play real instruments? Because playing real instruments is hard. I know. I played the guitar daily for about a three-year period. In that time, I mastered 10 chords or so. You could say I had a repertoire of about a dozen songs, but only if you were being charitable toward me, and uncharitable toward the songs. This was something I put hundreds of hours of my life into, and I never progressed past the "woeful beginner" stage. It's no wonder -- in Outliers, Malcolm Gladwell cites research suggesting that approximately 10,000 hours of practice are necessary to master anything.
That's just one musician! It's even harder to get a whole band together. You need at least three people for a band, preferably four -- even, in the case of the E Street Band, several hundred. We're looking at 30,000 man-hours, minimum, just to get enough musicians together to start a decent band. But it's not enough to find people who are proficient at their instruments. They have to share a musical vision, and have the time and commitment necessary to write songs, practice, play gigs, and so on. When you look at it that way, it's a wonder there are any bands around at all, never mind good ones.
Guitar Hero and Rock Band are hard, too, but much less so, and with a much lower barrier of entry. Almost anyone can instantly get the hang of easy difficulty, and start playing whole songs right away. Even medium difficulty is within the grasp of many first-time players. It takes a while to get good enough to handle expert difficulty, but certainly not 10,000 hours.* Here's the real difference: you don't have to be an expert to play the songs and enjoy the games. If you have four people and the necessary equipment, you can tackle any song in the Rock Band library, regardless of each participant's level of ability. It doesn't really matter whether you're good at it or not. That isn't the case with real instruments, even if you're just noodling around at home.
So there you go. There's your answer. Playing instruments: hard. Playing Guitar Hero: easy.
I suspect that's not satisfying to the critics, and I'll admit that it's not satisfying to me. The reason why that's so is because the premise -- that playing Guitar Hero and Rock Band is a substitute for playing real instruments -- is false. Tomorrow, I'll explain why.
Continue to part two.
*It may very well take 10,000 hours to be able to play everything flawlessly on expert difficulty. God knows I can't do it.
Labels: Guitar Hero, Rock Band
Quinn said...
I like the logic behind the arguments that Wii remote waggling in Manhunt 2 was bad because it trained gamers to be sociopathic murderers, but button-pushing in Guitar Hero et al is bad because it doesn't train us to be rock virtuosos.
Granted, I don't know that one person ever made both arguments, but there's still an interesting double standard at work here.
It seems like the "why don't you play a real instrument?" argument usually comes from people who don't enjoy those games.
I don't enjoy playing Madden, but I don't ask those players "why don't you go play NFL football?"
It's crazy to me that people think that such criticism is valid. Even some whose opinions I normally respect.
Quinn, that's dead on. It's just like the way games turn people into dead-eyed zombies who never leave the house -- or, wait, are they violent psychopaths?
Coleman, I think you'll enjoy tomorrow's post.
Heh, I read Outliers about a month ago and thought the same. I'm not that hardcore about RB, but we host Sunday night rock sessions. Still, I'd be shocked if we ever got to 100 hours with the game.
Even if we did, that would be about 1% of the time needed to be decent. So instead of spending that time having a ton of fun with my fiancée and friends, we could have been suffering though the most painful part of musicianship and still have 9,900 hours left to go? Sounds like a great arrangement to me.
And why play a racing game when you can go learn to drive a real race car? And why play a shooter when you can just join the military?
"And why play a shooter when you can just join the military?"
Now that you mention it...
Mitch! I am loving this train of thought. I have been recently voyaging down the same line of thinking, though from a slightly different angle.
A little background: I'm a professional musician, and I dearly love video games as well. (I actually have a super-epic new album out, you can hear tracks here, if you're interested.) Ever since discovering Rock Band, I have been fascinated by the confluence between music and interactive entertainment that games like RB and GHWT are signaling. I've been trying to get my head around the implications for some time.
I agree that playing an actual instrument is in no way comparable to playing Guitar Hero. When you really think about it, it is clearly a facile comparison, and one meant to kill any meaningful discussion about the musical implications of music games.
However, there IS something there that is very interesting to me -namely, the way in which GH and Rock Band can bring together musicians and non-musicians in very real musical performance, something I think is both unprecedented and massively exciting.
The thing that set it off for me was a pretty cool occurrence at a party a few months ago. We had set up Rock Band and it was the usual thing, a bunch of people kind of drunkenly playing and singing songs, very fun stuff.
At one point, however, my friend (who is a bad-ass rock singer) and I (who groove quite hard on the drums) jumped into the mix. We took on Boston's "Foreplay/Long Time," and I'm telling you: it was like there was a Boston show in my living room. We absolutely rocked it - our years of practice and performance were really able to come out, not in the precision with which we matched the notes on the screen, but with the rhythms, moves, and audible vocals - in the analog components of the (mostly-digital) game. From the opening riffs to the (usually stupid, but this time awesome) Big Rock Ending, it was a bona-fide performance.
But the best part about it was that the other two people who played bass and guitar were non-musician friends of ours, and it allowed the singer and me (who perform together all the time) to share a moment of genuine performance-bliss with friends with whom we've never shared it before. Everyone in the room was cheering and singing along, and it was honestly like getting to take those friends on stage with us.
It really affected me. These games are the first wave of some sort of great equalizer; a new, awesome way of uniting music creators with music listeners. It will probably always be on "real" musicians to create the source material, but the fact that we're seeing the beginnings of a new interactive medium, somewhere between playing music together and dancing to music together, is very exciting.
And, hell; as technology improves and the line between composition and user-generated content blurs, it should get even cooler!
So, yeah - like I said, my thoughts on the matter are unfinished. Sorry for the long comment, but I really like your blog, and was excited to see you tackle this topic, one in which I am (clearly ;-) very interested.
And again, if anyone's interested, I have a new album out, and I'm very excited about it. Tracks are streaming at http://myspace.com/kirkhamilton.
"There's your answer. Playing instruments: hard. Playing Guitar Hero: easy."
Mitch, when you suspect that's not a satisfying answer, it's no doubt because that's the real, underlying criticism being leveled at GH/RB by proper musicians: we've shortcut all of the (that is, all of their) work and gone straight to the fun--how dare we! But that's exactly what Kirk (and xkcd) hit on, and I imagine what your next post may touch on as well.
Nate P. said...
Tyler: I have actually seen people use the "Sim racing games are boring because I can drive in real life" argument in all sincerity. They must have some exciting 175-MPH trips to the grocery store in their Ferrari F355s. (Of course, I've also seen certain otherwise-thoughtful game reviewers use the "I can't blow up my opponents so this racing game is boring" argument, so...)
Yeah, I completely agree. For me, the more interesting comparison is comparing Rock Band to just listening to recorded music. Is listening to recorded music a bad thing or a good thing? Does pressing buttons while doing so make it worse or better? I know I've learned something about pieces of music while playing Rock Band (and in particular I was struck by how much more of the harmonic complexity comes out in expert guitar than in hard on some of the songs); and I've learned different things about the same piece while playing it on different instruments.
Kirk's comment is really interesting.
Kirk, an awesome comment. Thanks for posting it. And without going too much into what's coming in the next post, it's basically that these games are related to music, but they are not a substitute for music. Maybe it helps to have musical talent, but maybe it doesn't. More to the point, it doesn't matter! And that's a good thing, as you say. It's weird when people make an elitist, exclusionary argument when people are just enjoying some rock music.
David, I fully agree. Playing these games has actually educated me about these songs I've been listening to for years. I'm the kind of music listener who doesn't really hear anything except what's highest in the mix, be it vocals or a guitar solo or whatever. Guitar Hero and Rock Band have helped me appreciate basslines and drum beats in a way I never did before.
Exclusive Video Games said...
lol..great read..very entertaining.
F.E.A.R. 2 review; or, How I reached so hard for a...
Lifezone
A peripheral concern
The argument about Guitar Hero that I never want t...
Anchorage aweigh
Request hour: Sound effects, great writers, and PC...
Request hour: Browser games, and the birds and bees
Request hour: Dinner for four, emulation nation, a...
Request hour: The hardcasualist's lament, review s...
Request hour: Defining genre, living the dream, an...
Request hour: It begins
Insult Swordfighting request hour


accurate description. not have box polyethylene foam and wrapped tight and. обмотаны tape. store recommend. fast shipping pretty. one pair i have more size 41. suitable for 39-40-41. sell 2800 usd. spb avito in the search. motorboats.
Я заказала мотоботы 11 размера, но продавец по ошибке выслал 9,5 размер. Мной был открыт спор и продавец вернул часть денег. Мотоботы мы оставили себе. Про размер скажу что 9,5 на наш 43 малы.
Shoe soft and comfortable, good finish, excellent manufactory. Excellent value for money. Serious store and reliable. Recommended buy.


"The Look," by Roxette thumped in the background as I entered the empty dining room of Yoki, a new Japanese restaurant in Central Square. The plastic white walls changed colors every 20 seconds with rainbow lighting. It felt like Yoki was trying very hard to by hip and happening, but missed their target by a few decades.
I was a solo diner, grabbing a quick bite before Bridge. I ordered the Nigiri plate ($23), which was 10 pieces of sushi, 6 pieces of maki, and it came with miso soup and salad. My salad was ice cold, almost frozen, and drenched with the ubiquitous carrot ginger dressing. My sushi was inconsistently cut – some pieces were large and cumbersome, some were thin and ragged. The rolls were flavorless, as was most of the fish. The salmon was probably the only passable selection. I didn't have high expectations, but I've have better sushi from a supermarket. I'm going to bet that there will be a new restaurant in that space by next year.


My Blog Ranked as #29, The Top Oracle Blogs Around the world Here .
I would like to thank everyone for this and for the people who supporting me all the time.
Pleasure to be on the list with big names in Oracle world.
And Wish you to enjoy my blog more & more.


"At this point, it doesn't appear to be foreign-inspired," one U.S. security official said. "But the concern in France is that Islamists might take advantage of it."
The situation is being monitored by France's Central Directorate of General Intelligence, the police intelligence agency, and Directorate for Territorial Surveillance, the counterintelligence and security service.
One official said he thinks the riots "don't have a religious cast."
"What started out as juvenile delinquents engaging in vandalism is being taken over by Islamists," Mr. Emerson said, noting that Jewish targets indicate the Islamist bent of the rioters.
"It has already been taken over internally in France. The question is whether it will be taken over externally," he said.
"It certainly does," he said. "Not Islam the religion per se but the Islamists' separatist culture that is growing in France and other parts of the continent."
"It is not a directed part of the global extremist network, but it is an offshoot that is well-organized and has similar objectives in intimidating the French government, which they have done," Gen. McInerney said.
"It is an assimilation problem that Muslims have, and it will only eventually be resolved through an Islamic reformation," he said.
Harlan K. Ullman, a security adviser to the Center for Strategic and International Studies, said one problem highlighted by the riots is the growing role of fundamentalist Islam - not necessarily extremism - both in Europe and the United States.
"What we're seeing in France is a harbinger of things to come in the future here," Mr. Ullman said. "It could happen here, not in five years but perhaps 10 years."


While a truck jackknifing is normally associated with traffic jams, an out-of-control trailer can cause serious injuries and death. Failing to safely operate a truck by a driver who is inattentive, impaired or pressured to "make good time" can cause catastrophic accidents on the highways and freeways of Georgia.
What Factors Caused Your Accident?
The attorneys at Westmoreland, Patterson, Moseley & Hinson, L.L.P., combine over 200 years of experience in truck accident litigation coupled with a track record of multimillion-dollar results. Insurance companies who focus on the trucking industry employ vast resources and move quickly to investigate an accident and offer fast settlements to accident victims or grieving family members.
We counter that aggressive approach with our own team of experts that includes accident reconstructionists and engineers to help us build fact-based claims. They conduct on-site investigations and analyze the data from the truck's black box.
Call our firm at 888-469-4173 to arrange a no-cost consultation. Or, if you prefer, complete the online form. From offices in Macon, Albany and Warner Robins, our lawyer help clients statewide in Georgia and throughout the Southeast. You will owe no fees unless we recover compensation for you.


text:
import {
  IntersectionObserverPolyfill,
  nativeIntersectionObserverSupported,
} from '../../../../src/intersection-observer-polyfill';
import {
  VisibilityManagerForDoc,
  VisibilityManagerForEmbed,
} from '../visibility-manager';
import {VisibilityState} from '../../../../src/visibility-state';
import {documentStateFor} from '../../../../src/services';
import {layoutRectLtwh, rectIntersection} from '../../../../src/layout-rect';

class IntersectionObserverStub {

  constructor(callback, options) {
    this.callback = callback;
    this.options = options;
    this.elements = [];
    this.disconnected = false;
  }

  observe(element) {
    if (this.disconnected) {
      throw new Error('disconnected');
    }
    if (!this.elements.includes(element)) {
      this.elements.push(element);
    }
  }

  unobserve(element) {
    if (this.disconnected) {
      throw new Error('disconnected');
    }
    const index = this.elements.indexOf(element);
    if (index == -1) {
      throw new Error('element not found');
    }
    this.elements.splice(index, 1);
  }

  disconnect() {
    if (this.disconnected) {
      throw new Error('disconnected');
    }
    this.disconnected = true;
  }
}

describes.fakeWin('VisibilityManagerForDoc', {amp: true}, env => {
  let win;
  let ampdoc;
  let clock;
  let viewer, viewport;
  let root;
  let startVisibilityHandlerCount;
  let eventResolver, eventPromise;

  beforeEach(() => {
    win = env.win;
    ampdoc = env.ampdoc;
    clock = sandbox.useFakeTimers();
    clock.tick(1);

    viewer = win.services.viewer.obj;
    sandbox.stub(viewer, 'getFirstVisibleTime', () => 1);
    viewport = win.services.viewport.obj;
    startVisibilityHandlerCount =
        viewer.visibilityObservable_.getHandlerCount();

    root = new VisibilityManagerForDoc(ampdoc);

    win.IntersectionObserver = IntersectionObserverStub;
    win.IntersectionObserverEntry = function() {};
    win.IntersectionObserverEntry.prototype.intersectionRatio = 1;

    eventPromise = new Promise(resolve => {
      eventResolver = resolve;
    });
  });

  it('should initialize correctly backgrounded', () => {
    viewer.setVisibilityState_(VisibilityState.HIDDEN);
    root = new VisibilityManagerForDoc(ampdoc);

    expect(root.parent).to.be.null;
    expect(root.ampdoc).to.equal(ampdoc);
    expect(root.getStartTime()).to.equal(viewer.getFirstVisibleTime());
    expect(root.isBackgrounded()).to.be.true;
    expect(root.isBackgroundedAtStart()).to.be.true;
    expect(root.children_).to.be.null;  // Don't take extra memory.

    // Will be initialized lazily
    expect(root.intersectionObserver_).to.be.null;

    // Root model starts invisible.
    expect(root.getRootVisibility()).to.equal(0);
  });

  it('should initialize correctly foregrounded', () => {
    expect(root.parent).to.be.null;
    expect(root.ampdoc).to.equal(ampdoc);
    expect(root.getStartTime()).to.equal(viewer.getFirstVisibleTime());
    expect(root.isBackgrounded()).to.be.false;
    expect(root.isBackgroundedAtStart()).to.be.false;

    // Will be initialized lazily
    expect(root.intersectionObserver_).to.be.null;

    // Root model starts invisible.
    expect(root.parent).to.be.null;
    expect(root.getRootVisibility()).to.equal(1);
  });

  it('should switch visibility based on viewer for main doc', () => {
    expect(viewer.visibilityObservable_.getHandlerCount())
        .equal(startVisibilityHandlerCount + 1);
    expect(root.getRootVisibility()).to.equal(1);

    // Go prerender.
    viewer.setVisibilityState_(VisibilityState.PRERENDER);
    expect(root.getRootVisibility()).to.equal(0);

    // Go hidden.
    viewer.setVisibilityState_(VisibilityState.HIDDEN);
    expect(root.getRootVisibility()).to.equal(0);

    // Go visible.
    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    expect(root.getRootVisibility()).to.equal(1);
    expect(root.getStartTime()).to.equal(viewer.getFirstVisibleTime());
  });

  it('should switch visibility for in-a-box', () => {
    win.AMP_MODE = {runtime: 'inabox'};
    root = new VisibilityManagerForDoc(ampdoc);

    // Check observer is correctly set.
    const inOb = root.intersectionObserver_;
    expect(inOb).to.be.instanceOf(IntersectionObserverStub);
    expect(inOb.elements).to.contain(win.document.documentElement);

    // Start as invisible.
    expect(root.getRootVisibility()).to.equal(0);

    // Unrelated event.
    const otherTarget = win.document.createElement('div');
    inOb.callback([{
      target: otherTarget,
      intersectionRatio: 0.3,
    }]);
    expect(root.getRootVisibility()).to.equal(0);

    // Move to the viewport.
    inOb.callback([
      {
        target: otherTarget,
        intersectionRatio: 0.5,
      },
      {
        target: win.document.documentElement,
        intersectionRatio: 0.3,
      },
    ]);
    expect(root.getRootVisibility()).to.equal(0.3);

    // Back out of viewport.
    inOb.callback([
      {
        target: win.document.documentElement,
        intersectionRatio: 0,
      },
    ]);
    expect(root.getRootVisibility()).to.equal(0);
  });

  it('should switch root model to no-visibility on dispose', () => {
    expect(root.getRootVisibility()).to.equal(1);
    root.dispose();
    expect(root.getRootVisibility()).to.equal(0);
  });

  it('should dispose everything', () => {
    const modelsDisposed = sandbox.spy();
    const modelsCalled = sandbox.spy();
    const otherTarget = win.document.createElement('div');
    const spec = {totalTimeMin: 10};
    root.listenRoot(spec, null, null, modelsCalled);
    root.listenElement(otherTarget, spec, null, null, modelsCalled);
    root.listenElement(
        otherTarget, {totalTimeMin: 20}, null, null, modelsCalled);
    expect(root.models_).to.have.length(3);
    root.models_.forEach(model => {
      model.unsubscribe(modelsDisposed);
    });
    const otherUnsubscribes = sandbox.spy();
    root.unsubscribe(otherUnsubscribes);
    root.unsubscribe(otherUnsubscribes);
    const inOb = root.intersectionObserver_;
    expect(inOb.elements).to.contain(otherTarget);

    root.dispose();

    // All other models have been disposed.
    expect(root.models_).to.have.length(0);
    expect(modelsCalled).to.not.be.called;
    expect(modelsDisposed.callCount).to.equal(3);

    // All other unsubscribes have been called.
    expect(otherUnsubscribes.callCount).to.equal(2);

    // Viewer and viewport have been unsubscribed.
    expect(viewer.visibilityObservable_.getHandlerCount())
        .equal(startVisibilityHandlerCount);

    // Intersection observer disconnected.
    expect(inOb.disconnected).to.be.true;
    expect(root.intersectionObserver_).to.be.null;
    expect(inOb.elements).to.not.contain(otherTarget);
  });

  it('should polyfill and dispose intersection observer', () => {
    delete win.IntersectionObserver;

    const startScrollCount = viewport.scrollObservable_.getHandlerCount();
    const startChangeCount = viewport.changeObservable_.getHandlerCount();

    // Check observer is correctly set.
    const inOb = root.getIntersectionObserver_();
    expect(inOb).to.be.instanceOf(IntersectionObserverPolyfill);
    expect(viewport.scrollObservable_.getHandlerCount())
        .to.equal(startScrollCount + 1);
    expect(viewport.changeObservable_.getHandlerCount())
        .to.equal(startChangeCount + 1);

    root.dispose();
    expect(viewport.scrollObservable_.getHandlerCount())
        .to.equal(startScrollCount);
    expect(viewport.changeObservable_.getHandlerCount())
        .to.equal(startChangeCount);
  });

  it('should support polyfill on non-amp root element', () => {
    delete win.IntersectionObserver;
    const inOb = root.getIntersectionObserver_();

    const rootElement = win.document.documentElement;
    root.listenElement(rootElement, {}, null, null, eventResolver);
    expect(root.models_).to.have.length(1);
    const model = root.models_[0];
    expect(inOb.observeEntries_).to.have.length(1);

    // AMP API is polyfilled.
    expect(rootElement.getLayoutBox).to.be.function;
    expect(rootElement.getOwner()).to.be.null;

    // Starts as invisible.
    expect(model.getVisibility_()).to.equal(0);

    // Trigger tick.
    sandbox.stub(viewport, 'getRect', () => {
      return layoutRectLtwh(0, 0, 100, 100);
    });
    sandbox.stub(viewport, 'getLayoutRect', element => {
      if (element == rootElement) {
        return layoutRectLtwh(0, 50, 100, 100);
      }
      return null;
    });
    expect(rootElement.getLayoutBox())
        .to.contain({left: 0, top: 50, width: 100, height: 100});
    viewport.scrollObservable_.fire({type: 'scroll'});
    expect(model.getVisibility_()).to.equal(0.5);

    return eventPromise.then(() => {
      expect(inOb.observeEntries_).to.have.length(0);
    });
  });

  it('should listen on root', () => {
    clock.tick(1);
    const disposed = sandbox.spy();
    const spec = {totalTimeMin: 10};
    root.listenRoot(spec, null, null, eventResolver);

    expect(root.models_).to.have.length(1);
    const model = root.models_[0];
    model.unsubscribe(disposed);
    expect(model.spec_.totalTimeMin).to.equal(10);
    expect(model.getVisibility_()).to.equal(1);

    // Go invisible.
    root.setRootVisibility(0);
    expect(model.getVisibility_()).to.equal(0);

    // Back to visible.
    root.setRootVisibility(1);
    expect(model.getVisibility_()).to.equal(1);

    // Fire event.
    clock.tick(11);
    return eventPromise.then(state => {
      expect(disposed).to.be.calledOnce;
      expect(root.models_).to.have.length(0);

      expect(state.totalVisibleTime).to.equal(10);
      expect(state.firstSeenTime).to.equal(1);
      expect(state.backgrounded).to.equal(0);
      expect(state.backgroundedAtStart).to.equal(0);
      expect(state.totalTime).to.equal(12);
    });
  });

  it('should listen on root with ready signal', () => {
    clock.tick(1);
    const disposed = sandbox.spy();
    const spec = {totalTimeMin: 0};
    const readyPromise = Promise.resolve().then(() => {
      clock.tick(21);
    });
    root.listenRoot(spec, readyPromise, null, eventResolver);

    expect(root.models_).to.have.length(1);
    const model = root.models_[0];
    model.unsubscribe(disposed);

    // Blocked by ready promise: visibility == 0.
    expect(model.getVisibility_()).to.equal(0);

    // Fire event.
    return eventPromise.then(state => {
      expect(model.getVisibility_()).to.equal(1);
      expect(disposed).to.be.calledOnce;
      expect(root.models_).to.have.length(0);

      expect(state.totalVisibleTime).to.equal(0);
      expect(state.firstSeenTime).to.equal(22);
      expect(state.backgrounded).to.equal(0);
      expect(state.backgroundedAtStart).to.equal(0);
      expect(state.totalTime).to.equal(22);
    });
  });

  it('should pass func to create readyReportPromise to model', () => {
    let testPromiseResolver;
    const disposed = sandbox.spy();
    const testPromise = new Promise(resolve => {
      testPromiseResolver = resolve;
    });
    root.listenRoot({}, null, () => {
      return testPromise;
    }, eventResolver);
    expect(root.models_).to.have.length(1);
    const model = root.models_[0];
    model.unsubscribe(disposed);
    clock.tick(11);
    testPromiseResolver();
    return eventPromise.then(state => {
      expect(disposed).to.be.calledOnce;
      expect(state.totalVisibleTime).to.equal(11);
      expect(state.totalTime).to.equal(11);
      expect(state.maxContinuousVisibleTime).to.equal(11);
    });
  });

  it('should unlisten root', () => {
    clock.tick(1);
    const disposed = sandbox.spy();
    const spec = {totalTimeMin: 10};
    const unlisten = root.listenRoot(spec, null, null, eventResolver);

    expect(root.models_).to.have.length(1);
    expect(Object.keys(root.trackedElements_)).to.have.length(0);
    expect(root.getIntersectionObserver_().elements).to.have.length(0);
    const model = root.models_[0];
    model.unsubscribe(disposed);

    unlisten();
    expect(root.models_).to.have.length(0);
    expect(disposed).to.be.calledOnce;
  });

  it('should listen on a element', () => {
    clock.tick(1);
    const disposed = sandbox.spy();
    const target = win.document.createElement('div');
    const spec = {totalTimeMin: 10};
    root.listenElement(target, spec, null, null, eventResolver);

    expect(root.models_).to.have.length(1);
    const model = root.models_[0];
    model.unsubscribe(disposed);
    expect(model.spec_.totalTimeMin).to.equal(10);
    expect(target.__AMP_VIS_ID).to.be.ok;
    expect(root.trackedElements_[target.__AMP_VIS_ID].element).to.equal(target);

    const inOb = root.getIntersectionObserver_();
    expect(inOb.elements).to.contain(target);
    expect(model.getVisibility_()).to.equal(0);

    // In viewport.
    inOb.callback([{
      target,
      intersectionRatio: 0.3,
    }]);
    expect(model.getVisibility_()).to.equal(0.3);

    // Go invisible on root.
    root.setRootVisibility(0);
    expect(model.getVisibility_()).to.equal(0);

    // Back to visible on root.
    root.setRootVisibility(1);
    expect(model.getVisibility_()).to.equal(0.3);

    // Fire event.
    clock.tick(11);
    return eventPromise.then(state => {
      expect(disposed).to.be.calledOnce;
      expect(root.models_).to.have.length(0);
      expect(root.trackedElements_[target.__AMP_VIS_ID]).to.not.exist;
      expect(inOb.elements).to.not.contain(target);

      expect(state.totalVisibleTime).to.equal(10);
      expect(state.firstSeenTime).to.equal(1);
      expect(state.backgrounded).to.equal(0);
      expect(state.backgroundedAtStart).to.equal(0);
      expect(state.totalTime).to.equal(12);

      expect(state.elementX).to.be.undefined;
    });
  });

  it('should protect from invalid intersection values', () => {
    const target = win.document.createElement('div');
    root.listenElement(target, {}, null, null, eventResolver);
    expect(root.models_).to.have.length(1);
    const model = root.models_[0];

    const inOb = root.getIntersectionObserver_();
    expect(model.getVisibility_()).to.equal(0);

    // Valid value.
    inOb.callback([{target, intersectionRatio: 0.3}]);
    expect(model.getVisibility_()).to.equal(0.3);

    // Invalid negative value.
    inOb.callback([{target, intersectionRatio: -0.01}]);
    expect(model.getVisibility_()).to.equal(0);

    inOb.callback([{target, intersectionRatio: -1000}]);
    expect(model.getVisibility_()).to.equal(0);

    // Invalid overflow value.
    inOb.callback([{target, intersectionRatio: 1.01}]);
    expect(model.getVisibility_()).to.equal(1);

    inOb.callback([{target, intersectionRatio: 1000}]);
    expect(model.getVisibility_()).to.equal(1);
  });

  it('should listen on a element with different specs', () => {
    clock.tick(1);
    const inOb = root.getIntersectionObserver_();
    const target = win.document.createElement('div');

    // Listen to the first spec.
    const disposed1 = sandbox.spy();
    const spec1 = {totalTimeMin: 10};
    root.listenElement(target, spec1, null, null, eventResolver);
    expect(root.models_).to.have.length(1);
    const model1 = root.models_[0];
    expect(model1.spec_.totalTimeMin).to.equal(10);
    model1.unsubscribe(disposed1);
    expect(target.__AMP_VIS_ID).to.be.ok;
    const trackedElement = root.trackedElements_[target.__AMP_VIS_ID];
    expect(trackedElement.element).to.equal(target);
    expect(trackedElement.listeners).to.have.length(1);
    expect(inOb.elements).to.contain(target);

    // In viewport.
    inOb.callback([{
      target,
      intersectionRatio: 0.3,
    }]);
    expect(model1.getVisibility_()).to.equal(0.3);
    expect(trackedElement.intersectionRatio).to.equal(0.3);

    // Second spec on the same element.
    const disposed2 = sandbox.spy();
    const spec2 = {totalTimeMin: 20};
    let eventResolver2;
    const eventPromise2 = new Promise(resolve => {
      eventResolver2 = resolve;
    });
    root.listenElement(target, spec2, null, null, eventResolver2);
    expect(root.models_).to.have.length(2);
    const model2 = root.models_[1];
    expect(model2.spec_.totalTimeMin).to.equal(20);
    model2.unsubscribe(disposed2);
    expect(trackedElement.listeners).to.have.length(2);
    // Immediately visible.
    expect(model2.getVisibility_()).to.equal(0.3);

    // Fire the first event.
    clock.tick(11);
    return eventPromise.then(state => {
      // First event fired. The first model should be cleaned up, but not
      // the other.
      expect(state.totalVisibleTime).to.equal(10);
      expect(disposed1).to.be.calledOnce;
      expect(root.models_).to.have.length(1);
      expect(root.trackedElements_[target.__AMP_VIS_ID])
          .to.equal(trackedElement);
      expect(trackedElement.listeners).to.have.length(1);
      expect(inOb.elements).to.contain(target);

      // Fire the second event.
      clock.tick(10);
      return eventPromise2;
    }).then(state => {
      // Second event fired. Everything should be released now.
      expect(state.totalVisibleTime).to.equal(20);
      expect(disposed2).to.be.calledOnce;
      expect(root.models_).to.have.length(0);
      expect(root.trackedElements_[target.__AMP_VIS_ID]).to.not.exist;
      expect(trackedElement.listeners).to.have.length(0);
      expect(inOb.elements).to.not.contain(target);
    });
  });

  it('should listen on a resource', () => {
    clock.tick(1);
    const target = win.document.createElement('div');
    const resource = {
      getLayoutBox() {
        return {top: 10, left: 11, width: 110, height: 111};
      },
    };
    const resources = win.services.resources.obj;
    sandbox.stub(resources, 'getResourceForElementOptional',
        () => resource);
    const spec = {totalTimeMin: 10};
    root.listenElement(target, spec, null, null, eventResolver);

    const inOb = root.getIntersectionObserver_();
    inOb.callback([{
      target,
      intersectionRatio: 0.3,
    }]);

    // Fire event.
    clock.tick(11);
    return eventPromise.then(state => {
      expect(state.totalVisibleTime).to.equal(10);
      expect(state.elementY).to.equal(10);
      expect(state.elementX).to.equal(11);
      expect(state.elementWidth).to.equal(110);
      expect(state.elementHeight).to.equal(111);
    });
  });
});

describes.realWin('EmbedAnalyticsRoot', {
  amp: {ampdoc: 'fie'},
}, env => {
  let parentWin;
  let win;
  let ampdoc;
  let embed;
  let clock;
  let viewer;
  let parentRoot;
  let root;
  let inob;

  beforeEach(() => {
    parentWin = env.parentWin;
    win = env.win;
    ampdoc = env.ampdoc;
    embed = env.embed;
    embed.host = ampdoc.win.document.createElement('amp-host');
    clock = sandbox.useFakeTimers();
    clock.tick(1);

    viewer = parentWin.services.viewer.obj;
    sandbox.stub(viewer, 'getFirstVisibleTime', () => 1);

    parentRoot = new VisibilityManagerForDoc(ampdoc);
    parentWin.IntersectionObserver = IntersectionObserverStub;
    parentWin.IntersectionObserverEntry = function() {};
    parentWin.IntersectionObserverEntry.prototype.intersectionRatio = 1;

    root = new VisibilityManagerForEmbed(parentRoot, embed);
    inob = parentRoot.getIntersectionObserver_();
  });

  it('should dispose with parent', () => {
    const unsubscribeSpy = sandbox.spy();
    root.unsubscribe(unsubscribeSpy);

    expect(parentRoot.children_).to.have.length(1);
    expect(parentRoot.children_[0]).to.equal(root);

    parentRoot.dispose();
    expect(parentRoot.children_).to.have.length(0);
    expect(unsubscribeSpy).to.be.calledOnce;
  });

  it('should remove from parent when disposed', () => {
    const unsubscribeSpy = sandbox.spy();
    root.unsubscribe(unsubscribeSpy);

    expect(parentRoot.children_).to.have.length(1);
    expect(parentRoot.children_[0]).to.equal(root);

    root.dispose();
    expect(parentRoot.children_).to.have.length(0);
    expect(unsubscribeSpy).to.be.calledOnce;
  });

  it('should initialize correctly backgrounded', () => {
    viewer.setVisibilityState_(VisibilityState.HIDDEN);
    root = new VisibilityManagerForEmbed(parentRoot, embed);

    expect(root.parent).to.equal(parentRoot);
    expect(root.ampdoc).to.equal(ampdoc);
    expect(root.getStartTime()).to.equal(embed.getStartTime());
    expect(root.isBackgrounded()).to.be.true;
    expect(root.isBackgroundedAtStart()).to.be.true;

    // Root model starts invisible.
    expect(root.getRootVisibility()).to.equal(0);
  });

  it('should initialize correctly foregrounded', () => {
    expect(root.parent).to.equal(parentRoot);
    expect(root.ampdoc).to.equal(ampdoc);
    expect(root.getStartTime()).to.equal(embed.getStartTime());
    expect(root.isBackgrounded()).to.be.false;
    expect(root.isBackgroundedAtStart()).to.be.false;

    // Root model starts invisible.
    root.setRootVisibility(1);
    expect(root.getRootVisibility()).to.equal(1);
  });

  it('should ask parent to observe host element', () => {
    const id = embed.host.__AMP_VIS_ID;
    expect(parentRoot.trackedElements_[id]).to.be.ok;

    root.dispose();
    expect(parentRoot.trackedElements_[id]).to.be.undefined;
  });

  it('should delegate observation to parent', () => {
    const inOb = {
      observe: sandbox.spy(),
      unobserve: sandbox.spy(),
    };
    parentRoot.intersectionObserver_ = inOb;

    const listener = sandbox.spy();
    const target = win.document.createElement('div');

    // Observe.
    const unlisten = root.observe(target, listener);
    expect(inOb.observe).to.be.calledOnce;
    expect(inOb.observe).to.be.calledWith(target);
    const id = target.__AMP_VIS_ID;
    expect(parentRoot.trackedElements_[id]).to.be.ok;

    // Unobserve.
    unlisten();
    expect(inOb.unobserve).to.be.calledOnce;
    expect(inOb.unobserve).to.be.calledWith(target);
    expect(parentRoot.trackedElements_[id]).to.be.undefined;
  });

  it('should depend on parent for visibility', () => {
    const callbackSpy = sandbox.spy();
    const otherTarget = win.document.createElement('div');
    root.listenRoot({}, null, null, callbackSpy);
    expect(root.models_).to.have.length(1);
    const rootModel = root.models_[0];

    root.listenElement(otherTarget, {}, null, null, callbackSpy);
    expect(root.models_).to.have.length(2);
    const elementModel = root.models_[1];

    // Set up.
    expect(inob.elements).to.contain(embed.host);
    expect(inob.elements).to.contain(otherTarget);

    // Start state.
    expect(parentRoot.getRootVisibility()).to.equal(1);
    expect(root.getRootVisibility()).to.equal(0);
    expect(rootModel.getVisibility_()).to.equal(0);
    expect(elementModel.getVisibility_()).to.equal(0);

    // Make root visible.
    inob.callback([{
      target: embed.host,
      intersectionRatio: 0.5,
    }]);
    expect(root.getRootVisibility()).to.equal(0.5);
    expect(rootModel.getVisibility_()).to.equal(0.5);
    expect(elementModel.getVisibility_()).to.equal(0);

    // Make element visible.
    inob.callback([{
      target: otherTarget,
      intersectionRatio: 0.45,
    }]);
    expect(root.getRootVisibility()).to.equal(0.5);
    expect(rootModel.getVisibility_()).to.equal(0.5);
    expect(elementModel.getVisibility_()).to.equal(0.45);

    // Hide parent.
    viewer.setVisibilityState_(VisibilityState.HIDDEN);
    expect(parentRoot.getRootVisibility()).to.equal(0);
    expect(root.getRootVisibility()).to.equal(0);
    expect(rootModel.getVisibility_()).to.equal(0);
    expect(elementModel.getVisibility_()).to.equal(0);

    // Show parent.
    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    expect(parentRoot.getRootVisibility()).to.equal(1);
    expect(root.getRootVisibility()).to.equal(0.5);
    expect(rootModel.getVisibility_()).to.equal(0.5);
    expect(elementModel.getVisibility_()).to.equal(0.45);

    // Hide root.
    inob.callback([{
      target: embed.host,
      intersectionRatio: 0,
    }]);
    expect(root.getRootVisibility()).to.equal(0);
    expect(rootModel.getVisibility_()).to.equal(0);
    expect(elementModel.getVisibility_()).to.equal(0);

    // Update element.
    inob.callback([{
      target: otherTarget,
      intersectionRatio: 0.55,
    }]);
    expect(root.getRootVisibility()).to.equal(0);
    expect(rootModel.getVisibility_()).to.equal(0);
    expect(elementModel.getVisibility_()).to.equal(0);

    // Show root.
    inob.callback([{
      target: embed.host,
      intersectionRatio: 0.7,
    }]);
    expect(root.getRootVisibility()).to.equal(0.7);
    expect(rootModel.getVisibility_()).to.equal(0.7);
    expect(elementModel.getVisibility_()).to.equal(0.55);
  });
});

describes.realWin('VisibilityManager integrated', {amp: true}, env => {
  let win, doc;
  let ampdoc;
  let viewer;
  let resources;
  let clock, startTime;
  let scrollTop;
  let inObCallback;
  let observeSpy;
  let unobserveSpy;
  let visibility;
  let ampElement;
  let eventPromise, eventResolver;
  let eventPromise2, eventResolver2;
  let readyPromise, readyResolver;
  let readyReportPromise, readyReportResolver;

  beforeEach(() => {
    win = env.win;
    doc = win.document;
    ampdoc = env.ampdoc;
    viewer = win.services.viewer.obj;
    resources = win.services.resources.obj;

    observeSpy = sandbox.stub();
    unobserveSpy = sandbox.stub();
    const inob = callback => {
      inObCallback = callback;
      return {
        observe: observeSpy,
        unobserve: unobserveSpy,
      };
    };
    if (nativeIntersectionObserverSupported(ampdoc.win)) {
      sandbox.stub(win, 'IntersectionObserver', inob);
    } else {
      win.IntersectionObserver = inob;
      win.IntersectionObserverEntry = function() {};
      win.IntersectionObserverEntry.prototype.intersectionRatio = 0;
      expect(nativeIntersectionObserverSupported(ampdoc.win)).to.be.true;
    }

    readyPromise = new Promise(resolve => {
      readyResolver = resolve;
    });
    readyReportPromise = new Promise(resolve => {
      readyReportResolver = resolve;
    });
    eventPromise = new Promise(resolve => {
      eventResolver = resolve;
    });
    eventPromise2 = new Promise(resolve => {
      eventResolver2 = resolve;
    });

    const docState = documentStateFor(win);
    sandbox.stub(docState, 'isHidden', () => false);
    sandbox.stub(viewer, 'getFirstVisibleTime', () => startTime);

    ampElement = doc.createElement('amp-img');
    ampElement.id = 'abc';
    ampElement.setAttribute('width', '100');
    ampElement.setAttribute('height', '100');
    doc.body.appendChild(ampElement);
    return new Promise(resolve => {
      if (resources.getResourceForElementOptional(ampElement)) {
        resolve();
      } else {
        const interval = setInterval(() => {
          if (resources.getResourceForElementOptional(ampElement)) {
            clearInterval(interval);
            resolve();
          }
        }, 4);
      }
    }).then(() => {
      clock = sandbox.useFakeTimers();
      startTime = 10000;
      clock.tick(startTime);

      const resource = resources.getResourceForElement(ampElement);
      scrollTop = 10;
      sandbox.stub(resource, 'getLayoutBox',
          () => layoutRectLtwh(0, scrollTop, 100, 100));
    });
  });

  function fireIntersect(intersectPercent) {
    scrollTop = 100 - intersectPercent;
    const entry = makeIntersectionEntry(
        [0, scrollTop, 100, 100], [0, 0, 100, 100]);
    inObCallback([entry]);
  }

  function makeIntersectionEntry(boundingClientRect, rootBounds) {
    boundingClientRect = layoutRectLtwh.apply(null, boundingClientRect);
    rootBounds = layoutRectLtwh.apply(null, rootBounds);
    const intersect = rectIntersection(boundingClientRect, rootBounds);
    const ratio = (intersect.width * intersect.height) /
        (boundingClientRect.width * boundingClientRect.height);
    return {
      intersectionRect: intersect,
      boundingClientRect,
      rootBounds,
      intersectionRatio: ratio,
      target: ampElement,
    };
  }

  function isModelResolved(model) {
    return !model.eventResolver_;
  }

  it('should execute "visible" trigger with simple spec', () => {
    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    visibility = new VisibilityManagerForDoc(ampdoc);

    visibility.listenElement(ampElement, {}, readyPromise, () => {
      return readyReportPromise;
    }, eventResolver);

    return Promise.resolve().then(() => {
      clock.tick(100);
      fireIntersect(25); // visible
      readyResolver();
    }).then(() => {
      clock.tick(5);
      readyReportResolver();
      return eventPromise;
    }).then(state => {
      expect(state).to.contains({
        backgrounded: 0,
        backgroundedAtStart: 0,
        elementHeight: 100,
        elementWidth: 100,
        elementX: 0,
        elementY: 75,
        firstSeenTime: 100,
        lastSeenTime: 105,
        lastVisibleTime: 105,
        loadTimeVisibility: 25,
        maxVisiblePercentage: 25,
        minVisiblePercentage: 25,
        totalVisibleTime: 5,
        maxContinuousVisibleTime: 5,
      });
    });
  });

  it('should triger "visible" with no duration condition', () => {
    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    visibility = new VisibilityManagerForDoc(ampdoc);

    visibility.listenElement(
        ampElement,
        {visiblePercentageMin: 20},
        readyPromise,
        null,
        eventResolver);

    // add multiple triggers on the same element
    visibility.listenElement(
        ampElement,
        {visiblePercentageMin: 30},
        readyPromise,
        null,
        eventResolver2);

    // "observe" should not have been called since resource not loaded yet.
    expect(observeSpy).to.be.called;
    readyResolver();
    return Promise.resolve().then(() => {
      expect(observeSpy).to.be.calledWith(ampElement);

      clock.tick(135);
      fireIntersect(5); // below visiblePercentageMin, no trigger

      clock.tick(100);
      fireIntersect(25); // above spec 1 min visible, trigger callback 1
      return eventPromise.then(state => {
        expect(state).to.contains({
          backgrounded: 0,
          backgroundedAtStart: 0,
          elementHeight: 100,
          elementWidth: 100,
          elementX: 0,
          elementY: 75,
          firstSeenTime: 135,
          lastSeenTime: 235,
          lastVisibleTime: 235,
          loadTimeVisibility: 5,
          maxVisiblePercentage: 25,
          minVisiblePercentage: 25,
          totalVisibleTime: 0,  // duration metrics are always 0
          maxContinuousVisibleTime: 0,  // as it triggers immediately
        });
        expect(unobserveSpy).to.not.be.called;

        clock.tick(100);
        fireIntersect(35); // above spec 2 min visible, trigger callback 2
        return eventPromise2;
      }).then(state => {
        expect(state).to.contains({
          backgrounded: 0,
          backgroundedAtStart: 0,
          elementHeight: 100,
          elementWidth: 100,
          elementX: 0,
          elementY: 65,
          firstSeenTime: 135,
          lastSeenTime: 335,
          lastVisibleTime: 335,
          loadTimeVisibility: 5,
          maxVisiblePercentage: 35,
          minVisiblePercentage: 35,
          totalVisibleTime: 0,  // duration metrics is always 0
          maxContinuousVisibleTime: 0,  // as it triggers immediately
        });
      });
    }).then(() => {
      expect(unobserveSpy).to.be.called; // unobserve when all callback fired
    });
  });

  it('should trigger "visible" with duration condition', () => {
    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    visibility = new VisibilityManagerForDoc(ampdoc);

    visibility.listenElement(
        ampElement,
        {continuousTimeMin: 1000},
        readyPromise,
        null,
        eventResolver);
    const model = visibility.models_[0];

    readyResolver();
    return Promise.resolve().then(() => {
      expect(observeSpy).to.be.calledWith(ampElement);

      clock.tick(100);
      fireIntersect(25); // visible
      expect(isModelResolved(model)).to.be.false;

      clock.tick(999);
      fireIntersect(0); // this will reset the timer for continuous time
      expect(isModelResolved(model)).to.be.false;

      clock.tick(100);
      fireIntersect(5); // visible again.
      expect(isModelResolved(model)).to.be.false;

      clock.tick(100);
      // Enters background. this will reset the timer for continuous time
      viewer.setVisibilityState_(VisibilityState.HIDDEN);
      expect(isModelResolved(model)).to.be.false;

      clock.tick(2000); // this 2s should not be counted in visible time
      expect(isModelResolved(model)).to.be.false;
      viewer.setVisibilityState_(VisibilityState.VISIBLE); // now we're back

      clock.tick(100);
      fireIntersect(35); // keep being visible
      expect(isModelResolved(model)).to.be.false;
      clock.tick(899); // not yet!
      expect(isModelResolved(model)).to.be.false;
      clock.tick(1);  // now fire
      expect(isModelResolved(model)).to.be.true;
      return eventPromise.then(state => {
        expect(state).to.contains({
          backgrounded: 1,
          backgroundedAtStart: 0,
          elementHeight: 100,
          elementWidth: 100,
          elementX: 0,
          elementY: 65,
          firstSeenTime: 100,
          lastSeenTime: 4299,
          lastVisibleTime: 4299,
          loadTimeVisibility: 25,
          maxVisiblePercentage: 35,
          minVisiblePercentage: 5,
          totalVisibleTime: 2099,
          maxContinuousVisibleTime: 1000,
        });
      });
    });
  });

  it('should populate "backgrounded" and "backgroundedAtStart"', () => {
    viewer.setVisibilityState_(VisibilityState.HIDDEN);
    visibility = new VisibilityManagerForDoc(ampdoc);

    visibility.listenElement(
        ampElement,
        {},
        readyPromise,
        null,
        eventResolver);

    viewer.setVisibilityState_(VisibilityState.VISIBLE);
    readyResolver();
    return Promise.resolve().then(() => {
      expect(observeSpy).to.be.calledWith(ampElement);

      clock.tick(100);
      fireIntersect(25); // visible
      return eventPromise.then(state => {
        expect(state).to.contains({
          backgroundedAtStart: 1,
          backgrounded: 1,
        });
      });
    });
  });
});

redpajama_set_name: RedPajamaGithub


text:
/ Marvel
Doctor Strange in the Multiverse of Madness
Shang-Chi and the Legend of the Ten Rings
Falcon & The Winter Soldier
Marvel: Future Fight
Marvel: Contest Of Champions
Jessica Jones Season 3 Features Directorial Debut of Krysten Ritter
By Nicole Drum - June 15, 2019 02:19 pm EDT
The third and final season of Jessica Jones dropped on Netflix Friday. The 13-episode season marks the end of the Marvel Netflix shows with Luke Cage, Iron Fist, and The Punisher having already aired their final seasons, but it also marks a more positive milestone. Jessica Jones season three sees series star Krysten Ritter step away from her front-of-the-camera role as Jessica and go behind the lens in her directorial debut.
Warning: Possible spoilers for Jessica Jones season three below.
Ritter's directorial debut comes in episode two, "AKA You're Welcome." The episode centers on Trish Walker (Rachael Taylor) and her transformation of sorts. In the season two finale, it was teased that Trish had finally acquired the powers that she wanted so badly that she allows Karl Malus experiment on her and nearly kill her in the process when she drops her cell phone and catches on the top of her foot with incredible cat-like reflexes. Now, in season three, the episode shows Trish trying to be a vigilante hero herself in a very erratic, amateur sort of way as well as Trish's efforts to train and hone her powers in order to carry out her brand of justice. The episode both serves to show what Trish has been up to between the second and third seasons as well as show just how obsessed Trish is with the idea of being a hero with her powers -- and how jealous she is, on some level, of Jessica.
Ritter as director on an episode of the third season was first announced last June. At that time, Deadline reported that Ritter would take on the director role for a then-undisclosed episode, with Ritter expressing her excitement in a statement.
"I am beyond thrilled to make my directorial debut on Marvel's Jessica Jones," Ritter said last year. "The entire crew and cast has become family to me, and I'm so appreciative of the opportunity to work with our incredible team in this new way. I am so grateful that Melissa Rosenberg, Jeph Loeb, Marvel, and Netflix and entrusted me to take the reins."
It wasn't just Ritter who was excited, either. Showrunner Melissa Rosenberg had nothing but praise for Ritter's directorial debut in an interview last month.
"It's something she's wanted to do for a long time and is certainly qualified to do," Rosenberg told ComicBook.com. "She and I started talking about it last season as well, but she's in every scene of every episode so it just wasn't possible. And then, as we were creating season three in the writers' room, we realized the scene had even been written already and someone went 'Oh my god! She's not even really in this!' So, what a great opportunity."
As Rosenberg says, the episode she directed worked out smooth as it focuses on the ever-growing cast of Jessica Jones' supporting characters. According to the award-winning writer, it didn't take long for the teams at Marvel Television and Netflix to agree to give Ritter the chance to direct the show.
"Marvel agreed to it and Netflix did as well," reveals Rosenberg. "So I was able to hire her as a director and it was really very serendipitous that it worked out that way. She just fricking nailed it, man. There was no sign whatsoever that she was a first-time director. I've worked with directors with far more experience that were not even as near organized and specific"
Jessica Jones season three is now streaming on Netflix.
Black Widow Marvel Legends White Costume Figure is Available Now
Deadpool Movie Pays Tribute to Betty White on Her Birthday
Eminem Name-Drops Marvel's Thanos In New Surprise Album
Marvel: Crisis Protocol Previews Thor and Valkyrie
Iron Man Star Robert Downey Jr. Addresses Rumor Tony Stark Returns in Black Widow Movie
Taika Waititi's Star Wars Movie Could Put Akira and Thor: Love and Thunder in Jeopardy
Marvel Announces X-Men: God Loves, Man Kills Extended Cut
The Falcon and The Winter Soldier: Sebastian Stan Possibly Reveals New Look at Bucky Barnes


If one of your many duties as a parent is making lunch for the kids to take to school, then you need to check out these tips on how to prep and pack up to two weeks of school lunches.
From planning to grocery shopping to keeping all of your lunch stuff organized, we can help you fill those lunch boxes and bellies.
The first thing you need to do is figure out what you're going to make. If you have one kid, this is pretty simple. Ask them to give you ideas for what they'd like for lunch. If you have more than one kid, this could get tricky, especially if the two kids vary widely in age or preference. But get their input. Chances are, if you know what they like and can work those foods into their lunches. They're likely to eat everything they take to school with them.
Before you head to the grocery store, check out your pantry and take stock of what you already have. Then start making your shopping list. There are lots of menu planning apps and grocery list apps that can help. With a few clicks, you can add products to your list. The apps will usually sort them for you by section or aisle, and save you from wandering back and forth around the store for something that you might have forgotten. Some store apps, like Wegman's, will recognize the store you're in so that the locations (aisle numbers) of products change to match the store.
When you get home, try to save space in your cabinets or in your pantry just for lunch stuff. This will, hopefully, keep sneaky snackers from taking things off the shelves that you purchased just for lunches. If you have room and can set up baskets for each type of snack or even each kid in your family, that will help. You and the kids can just grab something from each basket, toss it in a lunch box, and go!
If you have time, make a batch of lunches all at once. You probably have a million other things going on in the morning, so this will save you from making lunches every day before school.
Are the kids sick of sandwiches? Try some fun lunch alternatives. Maybe send your kid to school with breakfast for lunch? You can easily pack a small box of cereal or microwaved oatmeal, fruits, juice, milk, and snacks.
Perhaps the kids can build a parfait at lunch. Pack some yogurt, granola, and fresh fruit that they can mix up however they like.
Maybe the older kids prefer salads, or maybe you just want your kids to eat more veggies? Make salads fun with lots of toppings: nuts, seeds, raisins, cranberries, peppers, carrots, celery, and croutons.
If you take care of the main dish, let the kids pick the sides. Have a snack bin set up in the pantry and/or fridge for the kids to choose things like veggie straws, popcorn, fruit chews, cheese sticks, and dessert items. You can even labeling them with a quantity that kids are allowed to pack, or let them choose one item per bin.
Here's an example of Keeley McGuire's week of make-ahead school lunches for her daughter. She has lots of great tips and advice for planning lunches in advance. You can use this menu as inspiration.
Day 1: Udi's GF Pizza Bagel (that she can reheat at school or eat at room temperature), baby carrots, and watermelon.
Day 2: Spinach salad topped with cheese, matchstick carrots, and a Mini Dipperwith dressing. She also had diced up cooked chicken breast for eating or topping on her salad, and pear slices.
Day 3: SunButter & Honey sandwich sticks on Udi's GF bread, a large carrot, grapes, and watermelon.
Day 4: Two Chocolate Chunk Pancake Muffins, a skewer of salami slices, fresh cut carrot sticks, and grapes.
Depending on the school cafeteria, your kids may have access to a microwave at lunchtime. If that's the case, there are all kinds of items you can stock up on at the store and send to school. You can try Hot Pockets, burritos, soups, PB&J Uncrustables, and even macaroni and cheese. Balance those out with some fruit, snacks, and a drink and your little one is all set.
Not a fan of pre-packaged foods? You can always make your own versions. There are copycat versions of just about any meal out there. Whether it's from the freezer section or your favorite restaurant, you can probably find a recipe on the Internet if you look hard enough.
What's the best thing about freezer recipes? You can make big batches in advance. There are tons of recipes on Pinterest. There are some websites that claim you can make 50 freezer meals in one day. These require lots of up-front prep, but imagine spending one day getting all of your shopping, chopping, and cooking done. You'd have over a month's worth of meals ready to go!
Older kids might be able to (should be able to) make their own lunches, so assign it to them as one of their responsibilities. If possible, make them pack their lunch the night before (and stash it in the fridge, if necessary) so all they have to do in the morning is grab it and go.
As mentioned above, if you have space somewhere in your kitchen, kids can grab their own lunch stuff and snacks. You can use a small plastic chest or metal craft cart, some baskets or tubs, and labels. Pre-portion your foods, snacks, and utensils, and the kids should be good to go. Check out this mom's ideas for a DIY lunch stations in both the fridge and pantry.
Make sure the kids get something from all of the food groups. Here are some ideas for go-to foods that are easy to prep, pack, and enjoy.
Add a treat or dessert. Don't forget utensils, napkins, and wipes.
Lunchables were the go-to snack for kids in the 80s and 90s but nowadays, parents question their health. There's a new spin on snack-sized lunches: the bento box. Bento boxes are a fun way to pack lunch, and they're easy to prep in advance.
You can buy both metal and plastic varieties, some of which may be microwave and dishwasher-safe. Some bento boxes come with separate individual containers with lids; others are just open compartments. (The open-compartment variety might be a smart choice for smaller kiddos as they won't have to struggle to open multiple containers.) They usually have a large compartment for the main dish, smaller spaces for sides and accompaniments, and sometimes sections for utensils or drinks.
A benefit of using the bento box is that you're not constantly using plastic baggies to pack up your snacks. And, you're not using a brown paper bag to carry everything. Since many bento boxes are leak-proof and can be tossed in the dishwasher, you don't have to worry about anything leaking and ruining a vinyl, canvas, or plastic lunch bag, or a backpack.
If the kids are going to reheat foods for lunch, make sure that you're using a recipe you know will taste just as good the next day. It also helps to make sure you're packing something that's easy to reheat and clean up.
To ensure the kids don't get bored with the same meal two days in a row, try switching it up a little bit. Use leftover chicken to make chicken salad wraps or to top leafy green salads. There are many simple ways to transform your leftovers.
When the weekend rolls around, you may still be on lunch duty. Instead of diving into bowls of cereal, make weekend brunch an event. This is the time to serve up and savor dishes you don't normally make for breakfast. Brunch is the best of both worlds, so there should be a little something to satisfy everybody. You can have your eggs and bacon, but have salads and sandwiches, too.
Food and Wine Magazine has a great spread online for kid-friendly brunch ideas. Check out this recipe for Food and Wine's ham and potato chip tortilla (Spanish omelet.) The kids will not resist eating potato chips for breakfast!
1. Preheat the broiler and position a rack 8 inches from the heat. In a large bowl, beat the eggs. Add the potato chips and mash to break them up.
2. In a large ovenproof nonstick skillet, heat the olive oil. Add the diced ham and sliced scallions. Cook over high heat for 1 minute. Add the eggs and cook until set on the bottom and side, about 3 minutes. Broil the tortilla for about 2 minutes until the top is lightly browned and the eggs are set. Slide the tortilla onto a plate, cut into wedges, and serve.
You can also let the kids return the favor and make lunch for you. Whether you make lunch together, simply supervise, or give the kids full permission to create their own lunch menu, it's nice to get in the kitchen together.


Discussion in 'Internet & WWW' started by billubakra, Mar 15, 2018.
Is there any way to move all sent and received mails via gmail to a particular folder? I can move the received mails from someone to a folder but the sent one remains in the sent tab. I need to move them also.
I assume you are doing this adding gmail as (additional email) to your primary email account (which you are using).


text:
Q: const is undefined in componentDidMount Im trying to make a const like this const feedURL = this.state.podcasts[0].feedUrl But the state is not updated with the fetch I do above where I set the state of podcasts, so i get TypeError: Cannot read property 'feedUrl' of undefined, that I understand.
But HOW should i get this to work? Anyone who can point me in the right direction..
This is my component:
import React, { Component } from 'react'
import Feed from 'feed-to-json-promise'
import sanitizeHtml from 'sanitize-html'

export default class Podcast extends Component {

  state = {
    podcasts: [],
    episodes: [],
    loading: true,
  }

  componentDidMount () {
    const podId = this.props.match.params.podId
    fetch(`https://itunes.apple.com/lookup?id=${podId}`)
      .then(response => response.json())
      .then(podcasts => this.setState({
        podcasts: podcasts.results,
        loading: false,
      }))

    const feed = new Feed()
    const feedURL = this.state.podcasts[0].feedUrl

    feed.load(feedURL)
      .then(feedInfo => this.setState({
        episodes: feedInfo.items
      }))
  }

    render() {
    const { podcasts, episodes, loading } = this.state
    const { podId } = this.props.match.params

    if (loading === true) return null
    const { collectionName, artworkUrl600, primaryGenreName, feedUrl } = podcasts.find((podcast) => podcast.collectionId === Number(podId))

    return (

{collectionName} ({podId})

{primaryGenreName}

RSS Feed URL

              {episodes.map((episode, i) => {
                const { title, description } = episode;
                return (

{title}

{sanitizeHtml(description, {allowedTags: [], allowedAttributes: []})}

                )
              })}

    )
  }
}


text:
Report: Climate change worsens Western water woes
April 25, 2011 at 7:15 a.m.
WASHINGTON—Climate change is likely to diminish already scarce water supplies in the Western United States, exacerbating problems for millions of water users in the West, according to a new government report.
A report released Monday by the Interior Department said annual flows in three prominent river basins—the Colorado, Rio Grande and San Joaquin—could decline by as much 8 percent to 14 percent over the next four decades. The three rivers provide water to eight states, from Wyoming to Texas and California, as well as to parts of Mexico.
The declining water supply comes as the West and Southwest, already among the fastest-growing parts of the country, continue to gain population.
Interior Secretary Ken Salazar called water the region's "lifeblood" and said small changes in snowpack and rainfall levels could have a major effect on tens of millions of people.
The report will help officials understand the long-term effects of climate change on Western water supplies, Salazar said, and will be the foundation for efforts to develop strategies for sustainable water resource management.
The report notes that projected changes in temperature and precipitation are likely to alter the timing and quantity of stream flows in all Western river basins, with increased flooding possible in the winter due to early snowmelt and water shortages in the summer due to reductions in spring and summer runoffs. Changes in climate could affect water supplies to a range of users, from farms and cities to hydropower plants, fish, wildlife and recreation, the report said.
Western states are growing faster than the rest of the country, with some of the fastest growth occurring in the driest areas, such as Nevada, Arizona and Texas.
"Impacts to water are on the leading edge of global climate change," said Mike Connor, commissioner of the Bureau of Reclamation, an Interior Department agency that provides water to more than 31 million people in 17 Western states and power to 3.5 million homes.
The report "affirms the urgency of the planning we are engaged in," Connor said at a news conference Monday. "We need to take actions now to plan" for changes that are likely to occur over the next several decades.
The report addresses the expected impact of climate change on eight major rivers basins in the central and Western United States. Besides the Colorado, Rio Grande and San Joaquin, the report also looks at the Columbia, Klamath and Sacramento rivers on the West Coast; the Missouri River Basin in the Northwest and Great Plains; and the Truckee River Basin in California and Nevada.
All eight basins should see an increase in temperature of about 5 to 7 degrees Fahrenheit by the end of the century, the report says. Four basins will see an increase in overall precipitation by 2050: the Upper Colorado, Columbia, Missouri and Sacramento, while four will see a decrease: the Lower Colorado, Rio Grande, San Joaquin and Truckee.
Reductions in spring and summer runoffs could lead to a drop in water supply in 6 of the 8 basins, the report said.
Due to early snowmelt and relatively higher winter rains from warmer conditions, all but the Colorado basin could become more vulnerable to floods, the report said.
Aiguo Dai, a climate scientist with the National Center for Atmospheric Research in Boulder, Colo., said the report echoes predictions he and other researchers have made that climate change would reduce stream flow rates in Western U.S. rivers. But he said computer models used to assess global trends would not be helpful for small river basins such as the Klamath or Upper Rio Grande.
Even regional models that take local topography into account "still contain large uncertainties," Dai said.
Sen. Jeff Bingaman, D-N.M., said the report did "a solid job" cataloguing Interior's efforts to respond to climate change. Bingaman, chairman of the Senate Energy and Natural Resources Committee, sponsored a 2009 law that aims to improve water management in the West and increase analysis of water-related data. The report released Monday was prepared in response to the Secure Water Act.
"Faced with forecasts of decreased stream flows and increased temperatures, it's more important than ever for communities to actively plan for changing conditions," Bingaman said. "In arid environments like New Mexico, every drop counts, and conservation and efficient water use are essential. Having tools available to accurately monitor existing water supplies, and to accurately predict future scenarios, can provide more certainty to water users and help decrease tensions."
Associated Press writer John Flesher in Traverse City, Mich., contributed to this report.
Colorado News |
Ex-Aurora police Chief Vanessa Wilson used position of power to have partner's ex-girlfriend arrested, lawsuit alleges
No criminal charges in fatal shooting inside Northglenn home
Women's basketball: Mature, talented CU Buffs navigating tough Pac-12 slate