text:
Joan Vos MacDonald
"Come and Hug Me" And The Ghost of Collective Punishment
June 22, 2018 by Joan Vos MacDonald
It's a common plot device for k-drama lovers to be conflicted between filial duty and romantic love, especially when one of the lovers is somehow complicit in crimes against the other lover's family. Being complicit does not necessarily mean committing a crime or even knowing about it. Just being related to the criminal can result in an overwhelming burden of guilt and shame that it makes a relationship impossible. In South Korea's past, being related to a criminal might have meant a death sentence.
In "Come and Hug Me," detective Chae Do Jin played by Jang Ki Yong, is the son of a serial killer, who murdered the parents of Han Jae Yi, played by Jin Ki Joo. The young lovers were separated by the brutal murder, only to reconnect a decade later when Han Jae Yi's life is again threatened.
In one scene, when Chae Do Jin is at the police academy, the other cadets whisper about his father. How could the son of a serial killer want to be a policeman? Has he no shame? Chae rightly points out that Korea no longer has collective punishment. This form of punishment judges and sentences people for their association with or relation to a person accused of a crime. During the Choson Dynasty, if one person received a death sentence, so might generations of his family members. It was a very effective punishment as it eliminated those who supported the criminal, often a dissident or a political enemy, and removed those likely to avenge him. It's also the most heartbreaking of punishments, knowing that none of your family will survive you. The punishment still exists in North Korea, numbering among the nation's many human rights abuses. Centuries have passed since it was practiced in South Korea.
Still, the story of Chae Do Jin proves that, while the law now punishes only the criminal, it's possible to be condemned by the sins of your father.
In "Come and Hug Me," no matter how hard Chae Do Jin tries to serve and protect people, there are some who would judge him by the actions of his insane father and want him punished for his father's crimes. If anything, Chae is trying, by his choice of profession and acts of self sacrifice, to atone for his father's sins. Chae is as much a victim of the killer, played by Heo Jun Ho, as any of his other victims. While he survived one of his father's murderous rages, his life is scarred by his father's reputation. His chance at a new start ends when his imprisoned father publishes a book detailing the crimes.
While there are some puzzling leaps of logic in this drama's story, the action moves along nicely because of the compelling performance of lead actor Jang Ki Yong, definitely one of k-drama's rising male stars. Jang played an alternate suitor to time-traveling Jang Na Ra in "Go Back Couple" and then aced the rather difficult role of brutal loan shark Lee Gwang Il in "My Mister," a character whose life forced him to sublimate all sense of decency. He portrays Chae Do Jin as a similarly complex character. Chae has learned to be tough and competent, in a comic book way, but underneath, he often cries and feels guilty for what his father has done.
Can Chae Do Jin ever break free of the life sentence his father condemned him to? Here's hoping for a k-drama ending where he's judged on his own merit and no longer feels guilty by association.
Photo courtesy MBC
Watch the drama on Viki.com. Here's a trailer:
Filed Under: Korean drama Tagged With: Come and Hug Me, Jang Ki Yong, kdrama
Previous PostSix Months Worth Of Stand Out K-Drama Characters
Next Post Are You Human Too? It's A Good Question
© 2020 Joan Vos MacDonald
website by Roman Creative


text:
LCI 96LCI(L)Story Archive
LCI(L)-96
The USS LCI National Association - September 17, 2017 September 18, 2017
By Richard "Dick" Kliemt
My name is Richard ("Dick") Kliemt. I was a Lieutenant in the US Coast Guard and the Engineering Officer aboard the USS LCI 96 during World War 2.
The LCI 96 was active in both the Atlantic and Pacific theaters of operation during World War 2. She made landings in Sicily, Italy and on the beaches at Normandy.
The Flotilla was #103 and #19 and was the only LCI group that was manned by the US Coast Guard.
After her duty in Europe , the "96" retraced her steps back to Norfolk, Virginia where she was re-outfitted for further duty in the Pacific I boarded her there as Lieutenant in charge of Engineering, maintaining the Grey Marine "Quads" that General Motors produced solely for the LCI.
In 1944 we took her through the Panama Canal up to San Diego. Here we were re-camouflaged and outfitted with smoke machines and new weapons We practiced making "landings" around San Clemente. We lost a few shipmates during those practice runs when a heavy surf washed a few men overboard despite some major effort to rescue them.
The "96" went across the Pacific where we transported troops and Naval personnel around the island of Ulithi and then over to Kerrama Rhetta and Okinawa where we fought off Kamikazes and "made smoke" covering the bigger ships of the fleet (including the "IOWA") and performed duty on the "picket line" which protected the fleet in Buckner Bay.
We encountered two typhoons during that tour of duty. After the "bomb" was dropped, the " 96 " was reassigned to the Navy Task Force in charge of clearing the mines in Japanese waters to allow the Occupation Troops and Ships to enter those waters.
As a "destruction" vessel the "96" detonated approximately 250 mines which were swept up by the Navy minesweepers we were assigned to. This was accomplished in the waters of the East China Sea, around Nagoya, Sasebo, Osaka and Wakayama.
In early 1946 we sailed the "96" back to the states and decommissioned her at San Pedro, California. Lieut., George Herrick (now deceased) and I were the only remaining personnel on board at that time.
The "96" was awarded a Commendation from the Commander of COMINPAC upon the completion of that assignment in which was stated that the" LCI proved that it could do most anything including what it was originally designed for."
The last we saw of her was when she was being towed out into San Pedro Bay with two other LCIs and put into the mothball fleet. That was in April or May of 1946. I was discharged the following day and returned back to New York. I am interested in trying to locate some of my shipmates…specifically Lieut. Sam Underwood of Maryland and Lieut. Owen B. Smith of Okeechobee Florida, and anyone else for that matter that can recall those hectic days we spent under "condition red" and those days after of the typhoon when we found ourselves washed ashore in Osaka.
Richard (Dick) Kliemt
Coast Guard Ship: Served in Normandy and Okinawa
Emergency Surgery on LCI 226
Joe Burden August 30, 2020 at 10:17 pm
My Grandfather, Charles Joseph Givens, was aboard that ship. I have a great picture of him playing an accordian while others played the guitar. Music after beer rations, 1945 was the caption on the side. He was from Chicago and Corpus Christi, TX. He sure was a character.

redpajama_set_name: RedPajamaCommonCrawl


Distribute your news to a growing number of subscribers.
NewsBox News Reader & Newswire currently require separate login.
The reason for this is because the News Reader platform is designed more for all users and has a mobile-friendly view. Newswire is designed for PR & IR and is best if accessed on a desktop or laptop.
If you have questions about your account or have general feedback, please e-mail us at support@newsbox.com.


text:
{-# LANGUAGE TemplateHaskell, QuasiQuotes, OverloadedStrings #-}
module Handler.Bling
    ( getBlingR
    ) where

import Import
import Settings.StaticFiles (bling_monads_in_disguise_png)

getBlingR :: Handler RepHtml
getBlingR = defaultLayout $ do
    setTitle "Haskell Bling"
    $(widgetFile "bling")

redpajama_set_name: RedPajamaGithub


text:
What Happened To The News Tab On Facebook
What Happened To The News Tab On Facebook?
In 2013, Facebook announced a new feature called the News Tab. This feature was designed to make it easier for users to find news stories on Facebook. The News Tab was initially available to a limited number of users, but it was eventually made available to all users.
However, in recent months, the News Tab has disappeared from Facebook. It is no longer available to users, and there is no indication that it will be returning in the near future.
So what happened to the News Tab?
There is no definitive answer to this question, but there are several possible explanations.
One possibility is that the News Tab was discontinued because it was not successful. Facebook has made a number of changes to its platform in recent years, and it is possible that the News Tab was discontinued because it was not popular or profitable.
Another possibility is that the News Tab was discontinued because it was not compliant with new GDPR regulations. The GDPR regulations, which came into effect in May 2018, are designed to protect user data and privacy. It is possible that the News Tab was discontinued because it did not meet the GDPR requirements.
Finally, it is possible that the News Tab was discontinued for other reasons, such as technical problems or a shift in Facebook's priorities.
At this point, it is unclear what happened to the News Tab, and Facebook has not provided any official explanation. It is possible that the News Tab will return in the future, but there is no guarantee that this will happen.
If you are looking for a way to find news stories on Facebook, you can try using the Facebook search bar. You can also try using news aggregator websites or apps, such as Google News or Apple News.
1 How do I get my Facebook News tab back?
2 What happened to the News section of Facebook?
3 What happened to the News button on Facebook 2022?
4 How do I get my Facebook News Feed back to normal 2022?
5 How do I add News to Facebook shortcut bar?
6 Where has most recent gone Facebook 2022?
How do I get my Facebook News tab back?
There are a few ways to get your Facebook News tab back. You can try going to the Facebook website and clicking on the "News Feed" option in the left-hand menu, or you can use the "News Feed" app on your phone or tablet. If you're not seeing the News Feed tab in either of those locations, you can try looking for the "News" section in the Facebook app.
See also What Is A Facebook Instant Experience
What happened to the News section of Facebook?
The News section of Facebook was a feature that allowed users to see a curated list of news stories from various sources. However, the News section was removed in early 2018 and has not been replaced.
There are several possible reasons for why the News section was removed. One possibility is that Facebook is trying to shift its focus away from news and towards social interaction. Another possibility is that Facebook is trying to crack down on fake news, and the News section was not effective enough in doing so.
Despite the removal of the News section, Facebook still allows users to view news stories on their News Feed. However, the process of finding news stories on Facebook has become much more difficult since the News section was removed.
What happened to the News button on Facebook 2022?
In 2022, Facebook removed the News button from its site, drawing criticism from users and media outlets alike.
The News button, which allowed users to see a list of recent news stories from their friends and other trusted sources, was removed as part of a broader redesign of the site.
Facebook said that the News button was being removed to make way for a new feature called "Today In", which would provide users with a roundup of local news stories.
Critics argued that the News button was being removed because it was unpopular with Facebook executives, who wanted to make the site more like Snapchat.
The News button was eventually reinstated in 2023, after a public outcry.
How do I get my Facebook News Feed back to normal 2022?
It can be really frustrating when your Facebook News Feed is cluttered with posts you don't want to see. Maybe you've tried to adjust your News Feed settings, but they still aren't working the way you want them to. If this is the case, don't worry – you can take steps to get your News Feed back to normal.
See also What Is A Public Page On Facebook
The first thing you can do is go to the News Feed Preferences page. Here, you can choose to see less posts from certain people, Pages, or groups. You can also choose to see more posts from certain people, Pages, or groups.
If you want to see more posts from a particular person, you can go to their profile and click on Following. Here, you can choose to see more or less posts from that person.
If you want to see more or less posts from a particular Page, you can go to that Page and click on Following. Here, you can choose to see more or less posts from that Page.
If you want to see more or less posts from a particular group, you can go to that group and click on Members. Here, you can choose to see more or less posts from that group.
You can also adjust your News Feed preferences on mobile devices. On the Facebook app, go to the Menu bar and tap on Settings. Here, tap on News Feed Preferences. You can then choose to see more or less posts from certain people, Pages, or groups.
If you're still not happy with your News Feed, you can try using the Facebook News Feed Preferences extension for Chrome. This extension allows you to hide posts from certain people, Pages, or groups.
Hopefully, these tips will help you get your Facebook News Feed back to normal.
How do I add News to Facebook shortcut bar?
Adding the News app to your Facebook shortcut bar will allow you to quickly and easily access the latest news stories from around the world. Here's how to do it:
1. Open Facebook and click on the "More" button at the bottom of the left-hand navigation bar.
2. Scroll down and click on "Add to Shortcuts."
3. Click on "News."
4. Click on the "Add to Shortcuts" button in the top right-hand corner of the News app.
5. The News app will now be added to your Facebook shortcut bar.
Where has most recent gone Facebook 2022?
See also Wall Street Journal And Facebook
There has been a lot of speculation recently about the future of Facebook. Many people are wondering where has most recent gone. In 2022, will Facebook still be around?
There are a few factors that could play into Facebook's future. First, its user base is starting to age. The youngest users are now in their early twenties, and as they age, they are less likely to use Facebook. Additionally, there are now more alternatives to Facebook, such as Snapchat and Instagram.
Facebook is also facing increasing competition from other social media platforms. In particular, Snapchat is growing rapidly, and its user base is much younger than Facebook's. Snapchat is also much more popular with teenagers and young adults.
If Facebook can't attract younger users, it will likely lose market share in the coming years. It's also possible that newer social media platforms will emerge and take over Facebook's market share.
So, will Facebook still be around in 2022? It's hard to say for sure, but there's a good chance that it will no longer be the dominant social media platform.
This is a question that a lot of people have been asking lately. Facebook removed the news button from its site back in 2022, and no one seems to know why.
Some people say that Facebook did this in order to make it easier for people to share news articles. Others say that the company removed the button because it was worried about being sued for promoting fake news.
Whatever the reason may be, the fact remains that the news button is no longer on Facebook. This has made it a lot harder for people to find news articles, and has led to a lot of confusion and frustration.
Fortunately, there are a few workarounds that you can use to get around this. You can either use a search engine to find news articles, or you can use a website that aggregates news stories from different sources.
Hopefully, Facebook will eventually bring back the news button, and things will return to the way they were. In the meantime, we'll just have to make do with the workarounds that are available.


Every day, Kristine Baker, RN, known as Kris, comes in to the GBMC Neonatal Intensive Care Unit (NICU) to care for the hospital's tiniest and most vulnerable patients, premature babies. These infants are living in an environment that they're wholly unprepared for and they need constant care and attention — some are born so sick that they can't eat or breathe on their own. They are sensitive to light and sound, and their skin may not even be able to tolerate being gently stroked or rubbed.
In the NICU, helping parents cope with their baby's condition is just as important as caring for the baby. No one plans for a child to end up in the NICU, so parents often find themselves unprepared and fearful of the future. Kris works to educate them about their baby's condition and helps them understand how he or she is developing.
Kris has been working in NICUs for the past 12 years and she forms strong bonds with the families of her patients, especially when they are there for extended stays. While this is incredibly fulfilling, it can be difficult when the family is struggling or the baby's health isn't improving as well as everyone had hoped. Kris makes sure to keep a positive focus, celebrating even the smallest of victories. "Being able to sit with families and comfort them is so rewarding," says Kris.
She never hesitates to give hugs or say prayers with a family; it's important to her that she meets every family where they are. One patient's family member described her this way: "She is able to face a distraught mother with just the right amount of empathy and respect for space." Like many NICU nurses, Kris cares so deeply about "her" families in the NICU that she maintains relationships with them well after their babies are healthy enough to go home.
This year, the proceeds from the Father's Day 5K benefit the new NICU unit being built at GBMC! The renovations will allow for increased privacy, more space for equipment, and refrigerated drawers for storing breast milk within patient rooms. Please join Kris and the rest of the NICU team as they run or walk to raise money for GBMC's tiniest patients on Sunday, June 17, 2018 at the 30th annual Father's Day 5K and Fun Walk. Click here to register or to support the event!


text:
$(document).ready(function() { if ($.cookie('noShowWelcome')) $('.hey-alert').hide(); else { $("#alrt").ready(function() { $(".hey-alert").fadeOut(10000); $.cookie('noShowWelcome', true); $('.hey-alert').click(function () { $('.hey-alert').hide(); }); }); } }); $(document).ready(function() { $('#list-eps').delay(3000).fadeIn(400); });
Elizabeth Debicki Movies
A Few Best Men HD
A groom and his three best men travel to the Australian outback for a wedding.
Country: Australia, UK
Director: Stephan Elliott
Actor: Rebel Wilson, Xavier Samuel, Olivia Newton-John, Kris Marshall, Kevin Bishop, Laura Brent, Tim Draxl, Solveig Walking, Elizabeth Debicki, Jonathan Biggins
Breath HD
A pair of teenagers in Western Australia looking to escape the monotony of life in a small town take up surfing lessons from a guy named Sando.
Genre: Drama, Sport
Director: Simon Baker
Actor: Simon Baker, Elizabeth Debicki, Samson Coulter, Ben Spence, Richard Roxburgh, Rachael Blake, Mike Dopud
Guardians of the Galaxy Vol. 2 HD
The Guardians must fight to keep their newfound family together as they unravel the mysteries of Peter Quill's true parentage.
Actor: Chris Pratt, Zoe Saldana, Dave Bautista, Vin Diesel, Bradley Cooper, Michael Rooker, Karen Gillan, Pom Klementieff, Elizabeth Debicki, Chris Sullivan
Macbeth HD
Macbeth, the Thane of Glamis, receives a prophecy from a trio of witches that one day he will become King of Scotland. Consumed by ambition and spurred to act..
Country: UK, France, USA
Director: Justin Kurzel
Actor: Michael Fassbender, Marion Cotillard, Paddy Considine, Sean Harris, Jack Reynor, Elizabeth Debicki, David Thewlis, David Hayman, Maurice Roeves, Ross Anderson
Peter Rabbit HD
Feature adaptation of Beatrix Potter's classic tale of a rebellious rabbit trying to sneak into a farmer's vegetable garden.
Genre: Animation, Adventure, Comedy
Director: Will Gluck
Actor: James Corden, Domhnall Gleeson, Rose Byrne, Daisy Ridley, Margot Robbie, Elizabeth Debicki, Sam Neill, Sia Furler, Vauxhall Jermaine, Terenia Edwards
Armed with only one word - Tenet - and fighting for the survival of the entire world, the Protagonist journeys through a twilight world of international espio..
Genre: Action, Thriller, Science-Fiction
Director: Andrés Barrientos,Steve Gehrke,Christopher Nolan,Martin Kildegaard Hem,Eric Richard Lasko,Nilo Otero
Actor: John David Washington, Robert Pattinson, Elizabeth Debicki, Kenneth Branagh, Dimple Kapadia, Himesh Patel, Aaron Taylor-Johnson, Michael Caine, Clémence Poésy, Martin Donovan
The Cloverfield Paradox HD
After a scientific experiment aboard the space station involving a particle accelerator has unexpected results, the astronauts find themselves isolated. Follo..
Genre: Horror, Mystery, Sci-Fi
Director: Julius Onah
Actor: Gugu Mbatha-Raw, Daniel Brühl, Elizabeth Debicki, David Oyelowo, Chris O'Dowd, John Ortiz, Aksel Hennie, Zhang Ziyi, Roger Davies
The Great Gatsby HD
A writer and wall street trader, Nick, finds himself drawn to the past and lifestyle of his millionaire neighbor, Jay Gatsby.
Country: USA, Australia
Director: Baz Luhrmann
Actor: Leonardo DiCaprio, Tobey Maguire, Carey Mulligan, Joel Edgerton, Elizabeth Debicki, Isla Fisher, Jason Clarke, Amitabh Bachchan, Callan McAuliffe, Adelaide Clemens
The Man from U.N.C.L.E. HD
In the early 1960s, CIA agent Napoleon Solo and KGB operative Illya Kuryakin participate in a joint mission against a mysterious criminal organization, which ..
Genre: Action, Adventure, Comedy
Director: Guy Ritchie
Actor: Henry Cavill, Armie Hammer, Alicia Vikander, Elizabeth Debicki, Luca Calvani, Sylvester Groth, Hugh Grant, Jared Harris, Simona Caparrini, Christian Berkel
The Tale HD
An investigation into one woman's memory as she's forced to re-examine her first sexual relationship and the stories we tell ourselves in order to survive.
Director: Jennifer Fox
Actor: Laura Dern, Isabelle Nélisse, Jason Ritter, Elizabeth Debicki, Ellen Burstyn, Common, John Heard, Frances Conroy, Isabella Amara, Laura Allen
Valerian and the City of a Thousand Planets HD
In the 28th century, Valerian and Laureline are special operatives charged with keeping order throughout the human territories. On assignment from the Ministe..
Country: Canada, France, China, Belgium, Germany, United Arab Emirates
Genre: Action, Adventure, Fantasy, Sci-Fi
Director: Luc Besson
Actor: Dane DeHaan, Cara Delevingne, Clive Owen, Rihanna, Ethan Hawke, Herbie Hancock, Kris Wu, Rutger Hauer, John Goodman, Elizabeth Debicki
Widows DVD
Set in contemporary Chicago, amid a time of turmoil, four women with nothing in common except a debt left behind by their dead husbands' criminal activities, ..
Director: Steve McQueen
Actor: Viola Davis, Michelle Rodriguez, Elizabeth Debicki, Cynthia Erivo, Colin Farrell, Brian Tyree Henry, Daniel Kaluuya, Jacki Weaver, Carrie Coon, Robert Duvall
Copyright 2020 © 123movies All Rights Reserved
123movies 123movies free GoMovies 123movieshub Free movies online Free online movies full Putlocker


Wages may be rising as the economy picks up but parents are still putting the squeeze on pocket money as figures show it has fallen by 2.4% in the last year.
The current weekly sum paid to eight to 15-year-olds has fallen to £6.20 compared with £6.35 in 2014, during a period when pay climbed by an average of 2%, according to an annual survey from lender Halifax.
However the figures indicate that over previous years children have seen much more generous increases in their allowances.
Past figures showed pocket money saw its biggest hike in 2003 when it doubled to £5.79, and it reached a peak of £8.37 in 2005 before turning lower. It fell back to £5.89 in 2010, in the wake of the financial crisis.
The latest Halifax data, from a survey of 1,200 children, also showed the number expected to work for their pocket money by doing household chores had fallen to 59% from 65% last year.
Bedroom tidying remains the most common task, followed by washing up, cleaning, and vacuuming.


Premium quality home in highly valuated area of El Higuerón. Everything is made to the perfection, including Siemens appliances in the kitchen. Views are unspeakably great, all the way to the Fuengirola harbour, mountains and city. Masterbedroom with en suite and second bedroom and bathroom. Openplan kitchen -livinroom area is spacious and luminous. Two parking places and large strage room. Three pools to be enjoyded, also barbeque area. The Hill Collection is build in 2017 and now it is ready for new owners.
El Higuerón is prestige and guarded area with a 5 * hotel and a Michelin star restaurant Sollo. Just few minutes to the beach and 10 minutes to Fuengirola. Definetly worth visiting, we have the keys, so do give us a call!


Drea Slee with her wonderful take on the challenge for this month.
My inspiration from this months beautiful work of art came from the colors and flowers. I used Bo Bunny's Serenity Collection, fussy cutting the branch, and two of the lanterns. I stamped the blue lantern, adding some machine stitching and beads. The flowers were made using my Serenity Blooms Tutorial, with the twist of fabric, which I used for the centers, and on all of the small flowers. I used permanent ink to stamp the small flowers onto muslin fabric, and cut around the edges, leaving some of the muslin exposed. Then I shaped them with some tacky glue mixed with a little bit of water. After it dried I added beads to the centers.
Here are a couple of samples of my work, one from each design team that I'm on.
I'm so very honored to be guest designing here this month, and can't wait to see all of your projects!!
Thank you so much for guesting with us on ARTastic this month Drea. I just love your unique style and wonderful use of paper on your pages. It has been delightful having you join us.
You still have until the end of the month to upload your own take on our challenge. We'd love to see what you can do with our inspiration artwork this month and our criteria of fabric (and remember "fabric" can be as simple as adding ribbon, lace, fabric flowers or even a yoyo or two to your page).
Welcome as a GD this month. Your pages are true work of art.


Appropriates moneys from General Fund to Secretary of State for certain biennial expenses.
Senate Jan 9, 2017: Introduction and first reading. Referred to President's desk.
Senate Jan 17, 2017: Referred to Ways and Means.
Senate Jan 24, 2017: Assigned to Subcommittee On General Government.
Senate Mar 21, 2017: Public Hearing held.
Senate Mar 22, 2017: Public Hearing held.
Senate Mar 23, 2017: Public Hearing held.
Senate Mar 27, 2017: Public Hearing held.
Senate Apr 20, 2017: Public Hearing held.
Senate Jun 28, 2017: Work Session held.
Senate Jun 28, 2017: Returned to Full Committee.
Senate Jul 1, 2017: Work Session held.
Senate Jul 3, 2017: Second reading.
Senate Jul 4, 2017: Third reading. Carried by Manning Jr. Passed.
House Jul 5, 2017: First reading. Referred to Speaker's desk.
House Jul 5, 2017: Referred to Ways and Means.
House Jul 6, 2017: Recommendation: Do pass.
House Jul 6, 2017: Second reading.
House Jul 6, 2017: Third reading. Carried by Nearman. Passed.
Senate Jul 18, 2017: President signed.
House Jul 18, 2017: Speaker signed.
Senate Jul 19, 2017: Governor signed.
Senate Jul 24, 2017: Chapter 602, 2017 Laws.
Senate Jul 24, 2017: Effective date, July 19, 2017.
Third reading. Carried by Manning Jr. Passed.
Third reading. Carried by Nearman. Passed.


Indoor amenities including a gym, music room, lounge and study area for students and more!
Westbank is a leading firm that went into business in 1992. With a portfolio that includes over 25 billion dollars in development, the company is known for their innovation and design.


text:
int getMinAbsoluteDifference(const std::vector<long int> & vector){
  long int difference = std::numeric_limits<long int>::max();
  for (long unsigned int i = 0; i < vector.size()-1; i++){
    int diff = std::abs(vector.at(i) - vector.at(i+1));
    if (diff < difference)
      difference = diff;
    else if (diff == 0)
      return diff;
  }
  return difference;
}

int main(){
  std::ios::sync_with_stdio(false);
  long int n;
  std::cin >> n;
  std::vector<long int> vector;
  for (long int i = 0; i < n; i++){
    long int v;
    std::cin >> v;
    vector.emplace_back(v);
  }
  std::sort(vector.begin(), vector.end());
  std::cout << getMinAbsoluteDifference(vector) << std::endl;

  return 0;
}


Who Are You Looking For In Sardinia, Ohio?
Run a search by name for anyone in Sardinia, Ohio & get free white pages information instantly. Sardinia, Ohio white page directory listings include full name, phone number and address.


thank you for allowing me to post on this forum.
I am an adult who was in a cult as a child thanks to my parents - they joined a cult when i was 4 and whole family was there until my teens.
Many years have passed since that time, and after many failed attempts to find a way to heal this year i think (after over 30 years!) i am slowly starting to regain some hope for at least some kind of recovery.
Now i am in the stage of my recovery when i try to actually glue together fragmented facts i remember and forgot, and i am trying to grasp the sense of actions of my abusers - my parents. I am writing down my memories, do some research/detective work, i interview witnesses (this is kinda dangerous : ( ) .
My primary struggle now - i can't quite get the internal logic for some actions of my abusers, why they were doing what they did, what were they thinking. Somehow it ís very important for me - i already managed to figure out some "why"s regarding part of my past and it felt very healing.
So i am looking for a proper place to ask my questions on why and get an insight from former survivors or people who study cults and cultmembers - do you think here is an appropriate place to try to do this?
If no - where is a good place to do that in your opinion?
May be there are some virtual/internet groups for people like me you can refer me to? One of the most crippling parts of experience is how isolating it is - for sure i can't mention my childhood on a cocktail party - so i am trying to break that isolation circle without ruining my life completely.
Thank you for reading, and i hope that my questions are appropriate for this forum. If not - i apologize.
Allow me to introduce myself, I am Marilyn Hargraves cousin. My mother and her mother were sisters. My mother's name was Mildred and her mother's name was Bessie. Bessie was part of the TLWF until Marilyn threw her out of the cult in the 90s. I have had no contact with Marilyn as an adult but several of my relatives have. I do have contact with and a good relationship with her brother, Charles and his wife.
To give you a little understanding of where I fit ... Marilyn and Charles were born almost two decades before I was. I'm actually closer in age to Marilyn's children than to Charles and Marilyn.
What I know about Marilyn, especially in later years comes from reports from my relatives. I decided early on that I would maintain a long distance from her.
When I tell people about Marilyn and this cult, I generally receive gasps and a few nervous laughs. Some people, including my wife didn't completely believe me ... that is, until she met Charles and his wife. What she learned shocked my wife to her core. My wife discovered that not only what I had said was true, but was actually worse than I had told her. Charles and his wife had more frequent contact with Marilyn and have been more tied into the information stream than I have been. Thus they were able to further educate us on the goings on.
What I have learned about Marilyn was that she had developed into an opportunist and a sociopath. She was someone who had absolutely no conscience. From all that I have heard about her, she learned that she loved power and manipulating people. And loved all the money she extracted from her followers, her believers and she continued to want more. I base this on all that I have heard over the years from my relatives and from what I know that she did to my Aunt, her mother. Bessie believed in and was devoted unquestionably to Marilyn. And in turn Marilyn took her mother for everything she had. One day, she threw her out of the cult. Bessie never understood the reasons for her explusion. Bessie died not long after it happened. I saw her shortly before she died.
Based on what I'm reading in this forum, Marilyn became exceptually good at giving into her desires and using her skills to exploit and manipulate people. What you have written aligns with what I have heard from my relatives about her activities.
My motivation posting this ... there's a high possibility that I would soon be passing through where Marilyn is buried and I considered paying my respects and placing a stone on her grave. Knowing that she's buried at what my relatives call "The Farm" (AKA Shiloh), I decided that it might be wise for me to do a little research on what's happening there. I ran across this forum and starting reading. Based on what I've been reading, I'm a little hesistant to drop by. So, I would appreciate anyone letting me know whether I should be concerned about dropping by, identifying myself and visit her grave. And if anyone is interested in asking me any questions about Marilyn and her involvement in the cult, I'd be happy to tell you what I know. Understand it will be hearsay information, but I think I can provide answers to some questions you might have, especially about the "early" Marilyn.
Hey pink. I grew up in Sam Fife's Move of God cult in the 70's and 80's. I was taken in at 3 years old until my mid teens. I suffered a lot of abuse. I wrote a book about it called "Cult Child". Where I have found the most support online is at places like this where I can meet and speak with others like me who understand the horror and the healing journey. Also, if you are on facebook, there is a great support group for women only called: Life After Cult Coercion Women's Support Group. I have received only loving support there and open sharing.
I'm here to talk with you as openly as you want. I suffered sexual, physical and mental abuse. I've also been on a very long healing journey so I understand many things to discuss.
Internal Logic: one thing I learned is that there is no logic with abusers. There isn't feeling or compassion. If there is, it's fake and has an end game. Everything they do has an end game and it always points back to them. They are sick and sadistic individuals committing the crime of undue influence on masses of people. I have a major question about the level of mind control it takes to get a parent to give over their child and not only let them be abused but worse, participate in it and believe, truly believe, they're doing good for a god.
What was your cult? Do you mind sharing which one you were taken into? I ask this to understand it's structure. For instance, my ex-Cult took all monies, so the members were left destitute, these such things.
The end goal of these predators is money and minds. I'm so sorry you were taken into this environment. I know the journey of reclaiming memories, and it's not a quick or an easy one.
I'm here holding space for you if you want to talk more. Sending you kind thoughts.


text:
Alaska » Sitka
Located at Sitka National Historical Park - AK (7 Projects)
Sitka National Historical Park: Lakich'inei Pole – Sitka AK
Lakich'inei Pole at Sitka
Source: National Park Service
Source National Park Service
Project type: Archaeology and History, Art Works, Historical Restoration, Sculptures
Agency: Civilian Conservation Corps (CCC), Works Progress Administration (WPA), Work Relief Programs
Started: 1938
Artists: George Benson (Lkeináa), Haida craftsmen, Tlingit craftsmen
Quality of Information: Very Good
Site Survival: Extant
The Civilian Conservation Corps (CCC) carved a copy of the original Lakich'inei Pole during a restoration program that lasted between 1938 and 1941. The restoration was part of a larger U.S. Forest Service program focused on the conservation of totems and Native cultural assets. Many of the poles that the CCC recovered were found in an advanced state deterioration, which made conservation difficult. While restoration was the preferred approach, the CCC opted for recarving, or partial recarving, if the pole could not be salvaged. The head carver at Sitka was George Benson. The pole was restored between 1992 and 1993.
Before the CCC program, many totems had been left to deteriorate in abandoned villages, as Native populations began to migrate in search of work opportunities. Leaving old totems to rot away was a longstanding Native practice. However, few new poles replaced the deteriorating ones in the early twentieth-century, as the art of totem carving gradually disappeared due to outmigration. In his 2012 volume, The Most Striking of Objects: The Totem Poles of Sitka National Historical Park, Andrew Patrick notes that the conversion of many Natives to Christianity also contributed to the disappearance of carving traditions. Citing Alison Hoagland (1997, 182), Patrick writes that young Natives from the village of Kake got together to destroy the poles and the bones of the dead with dynamite, while the elders watched in dismay. The new CCC program enlisted the help of master carvers such as George Benson, and began to train young recruits in the craft of totem carving, thus helping preserve not only Native artifacts, but also cultural practices.
In the volume The Most Striking of Objects, Andrew Patrick describes how the New Deal brought an influx of WPA and CCC funding, which helped with the conservation of the totem poles at Sitka: "The involvement of the WPA and the CCC with Sitka's totem poles began in January 1939. [B. Frank] Heintzleman secured WPA funding for totem pole restoration at Sitka National Monument. Work began on February 18th when Assistant Regional Forester Charles Burdick assessed, photographed, and numbered the poles. […] Funding switched from the WPA to the CCC just a month after the work first began. […] By March 22nd, 1940, all of the totem poles, except for Saanaheit's which was still being recarved, had been refurbished or replaced."
The National Park Service information page for the Sitka National Historical Park summarizes the characteristics and history of the pole: "Although the top figure of this pole is the subject of an ancient Tlingit legend, recent research indicates the original pole is from Sukkwan, a Kaigani Haida village that borders southern Tlingit country. Haida carvers may have learned of Tlingit crests and legends through travel, trade, and intermarriage, and incorporated them into poles carved for their own villages.
The top figure, Lakich'inei is pressing one of his children, who was half-human and half-dog, against his coat made from the spine of a fish, killing the child. The mid-pole figure appears to be Bear Who Married a Woman, also a legend found among the Tlingit, and the bottom figure is Bear with a snail or shrimp-like creature in his mouth.
Park records from 1939 indicate large areas of decay in the original pole that was donated by Johnny Kanow-Jones in 1903. Experts believe this pole is a copy of the original."
National Park Service, Sitka National Historical Park, Totem Trail, accessed August 24, 2017.
National Park Service, Sitka National Historical Park, Lakich'inei Pole, accessed August 24, 2017.
Larry Rakestraw, Totem Pole Restoration, Interview with Linn A. Forrest, August 1, 1971.
Hoagland, Alison K. "Totem poles and plank houses: reconstructing native culture in southeast Alaska." Perspectives in Vernacular Architecture 6 (1997): 174-185.
Patrick, Andrew. "The most striking of objects: the totem poles of Sitka National Historical Park." (2002), p. 104-121.
Project originally submitted by Brent McKee on August 24, 2017.
Sitka National Historical Park,
Coordinates: 57.04594042348921, -135.3146620550171
Sitka National Historical Park, Trader Legend Pole – Sitka AK
Sitka National Historical Park, Frog/Raven Pole – Sitka AK
Sitka National Historical Park, Saanaheit Pole – Sitka AK
Sitka National Historical Park, Gaanax.ádi/Raven Crest Pole – Sitka AK
Sitka National Historical Park: Totem Conservation Exhibit – Sitka AK
Sitka National Historical Park, The Mosquito Legend Pole – Sitka AK
View all projects at Sitka National Historical Park - AK (7 Projects)


text:
Police Address Concerns Surrounding Annual Hmong Freedom Festival
Filed Under:St. Paul News
ST. PAUL, Minn. (WCCO) — The St. Paul Police Department held a news conference Wednesday to address alleged threats relating to St. Paul's annual Hmong Freedom Festival.
"This is an important event for the city and want it safe for everyone," senior commander Sheri Falkowski said.
Falkowski said a flyer has been circulating around social media and has been brought to the department's attention by several community members. She said because the investigation remains active, she could not comment on the flyer's content, but police believe it originated within a small group.
"We're not going to let a small group of people ruin it for everyone," Falkowski said.
Falkowski said the department is taking the threats seriously, and there will be a "robust" police presence at and around the festival grounds. She added officers are working closely with event organizers, United Hmong Families, to ensure everyone remains safe.
Last year, a teen was shot and killed during the celebration in Como Regional Park.
RELATED: Teenager Killed In Shooting At Hmong Freedom Festival In St. Paul
The police are asking that anyone with information about the flyers to contact them.
The annual festival will go on as scheduled Saturday and Sunday at McMurray Fields in St. Paul.
2 Teenagers Accused In Over A Dozen Metro Area Carjackings
'We Can't Live In A Cave The Rest Of Our Lives': Restaurants, Attorney Speak Out About Lawsuit Against City Of Minneapolis
Minnesota Weather: Rounds Of Light Snow Expected Over The Weekend


Kati Basti is an Ayurvedic oil therapy for the low back. Organic flour is used to create a reservoir that is placed over the lumbar spine and sacrum. The pelvis, sacrum, lumbar spine, and colon are all considered home sites of Vata dosha, and will be places where the symptoms of Vata imbalance first express. Warm, medicated, herbal oils are poured inside the reservoir, concentrating the healing benefits of the oil where you need it most. The warm, unctuous, lubricating qualities of the oil counter the effects of excess cold, dry, rough, mobile Vata qualities in the lower body, nourishing spinal discs, and countering the effects of arthritis. As it calms Vata, it will leave you feeling deeply grounded and relaxed.
- swelling in the lumbar region, pregnancy, skin infection, current menstruation, or are unable to lie prone for 10+ minutes.
- Like most Ayurvedic therapies, it is advisable to not eat anything 90 minutes prior to your treatment.
- rest, gentle movement and/or asana is recommended for a few days following treatment. Avoid stress on the lumbar region while undergoing Kati Basti treatment.
Kati Basti is most therapeutic when experienced as a series of treatments. Please contact your Ayurvedic practitioner to inquire what kind of series would be most therapeutic for you.


text:
There Are 1.6M Cars With Illegal, Rolled-Back Odometers on US Roads, Carfax Says
Tampered odometers rip-off consumers at the time of purchase, but they also risk lives by hiding the true wear and tear of a car.
By Chris ChinApril 26, 2019
Odometer fraud has been an issue ever since the advent of the automobile—and it isn't going anywhere anytime soon. In fact, according to recent findings from NBC 12 with help from Carfax, there are as many as 1.6 million cars on the road across the United States that have had their mileage-counters rolled back.
This immoral (and criminal) act is a way to falsify a used car's value in that the lower mileage it has, the less it's been used. And a low-mileage car tends to command higher values than one with hundreds of thousands of miles on the clock.
"Our research shows there are now 1.6 million cars that are on roads across the country that have an odometer rolled back, and that's costing consumers millions of dollars," Chris Basso from Carfax told NBC 12.
Because of the computerization of automobiles and vehicle odometers, some are even saying that they're easier to roll back on newer cars. That's because it's as simple as connecting to a vehicle digitally and essentially hacking the car's main computer to fake the actual mileage reading. Well gee thanks, computers!
With older vehicles, tricksters had to physically disassemble a vehicle's gauge cluster to roll back the classic, analog "roller-style" odometers, which is a tedious and time-consuming task.
As an example, Carfax found a 2006 Chevrolet Silverado with 230,323 miles on it. With the help of a technician and a reportedly "inexpensive electronic device," they were able to deduct almost 100,000 miles off that number, leaving the Silverado to display only 130,483 miles.
"You're simply taking a device that hacks into the car's computer. You could take 100,000 miles off a car and artificially inflate the value of it by thousands of dollars, and you're ripping people off," continued Basso in an online video interview with NBC 12.
Not only is it a major form of deceit for the customer, but it can also result in major safety issues given that a car could have more wear and tear on it than falsely indicated in a rolled-back odometer.
In NBC 12's InvestigativeTV segment, reporters interviewed Erika Baez, who was a victim of odometer fraud in Midlothian, Virginia. Baez sold her Mercedes-Benz convertible and replaced it with a 2008 BMW from a dealer in northern Virginia, just outside Washington, D.C. The BMW had 136,507 when she purchased the vehicle, though Baez explained that she was convinced the mileage was inaccurate due to the number of problems she was experiencing with the car. In one instance, the wheel supposedly almost fell off, from what sounds like a terribly worn wheel bearing. After bringing it back to the dealer, Baez faced a nearly $5,000 repair estimate to fix all the problems.
When Baez referenced an AutoCheck report on her 2008 BMW, it showed the car sold new with 44 miles on it, then accumulated around 44,000 miles a few years later. Then there was a massive record gap in the history with the last reported mileage hovering around 218,000 miles. A Carfax report on her same vehicle also pointed out a potential odometer rollback situation and a major discrepancy in mileage.
"Definitely make sure you get the AutoCheck and the Carfax report. I would never buy another used car without having both reports from both sides," Baez told NBC 12.
Carfax Database Now Houses Over 20 Billion Data Records
A collision involving a 2010 Toyota Prius had the honor of becoming the 20 billionth accident reported.
Ferrari Salesman Blows Whistle, Says Ferrari Condones Odometer Rollback Device
According the the lawsuit, dealerships rolled back mileage to allow for inflated resale value—and it could only be done with Ferrari's blessing.
Lawsuit Suggests Ferrari May Have Known Dealers Were Using Official Tool to Roll Back Odometers
A former dealership employee is suing the company, claiming that the company knowingly allowed the practice.
These Are the Fastest- and Slowest-Selling Used Cars in America
Interesting patterns emerge surrounding America's taste in used cars, but what do they say about where the industry is headed?
With Used Cars, You Get What You Pay For
If you've come across a "good deal," take a closer look. It may not be, well, good.


text:
Q: Serial Over Lan doesn't redirect OS terminal I'm trying to create a monitoring system for a remote machine using an IPMI Serial Over Lan (SOL) console. The remote OS is RHEL 6, the mobo manufacturer is Supermicro.
I've successfully enabled SOL redirection in the BIOS. This allows me to see the BIOS and kernel parts of bootup through an attached SOL console over IPMI.
Next, I followed the steps mentioned in many online articles to get my OS ( runlevel 3, just text terminal ) to redirect too.
The result is almost always the same : After making the changes to /etc/grub.conf, /etc/inittab, and /etc/securetty, i can see the grub menu through the SOL console (yay!), but as soon as the OS starts booting, my SOL terminal receives 1 gibberish character, and nothing more.
For reference, this is my grub.conf :
serial --unit=1 --speed=115200 --word=8 --parity=no --stop=1
terminal --timeout=5 serial console
timeout=10
default=0

#splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu

title Red Hat Enterprise Linux (2.6.32-220.el6.i686)
    root (hd0,0)
    kernel /boot/vmlinuz-2.6.32-220.el6.i686 ro \
     root=UUID=5f8c255c-f997-4d6a-9af5-a133fc9229a0 rd_NO_LUKS \
     rhgb crashkernel=auto quiet biosdevname=0 LANG=en_US.UTF-8 rd_NO_MD quiet \
     SYSFONT=latarcyrheb-sun16 rhgb crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us \
     rd_NO_LVM rd_NO_DM serial console=tty0 console=ttyS1,115200n8
    initrd /boot/initramfs-2.6.32-220.el6.i686.img

I've added the following line to /etc/inittab:
S1:123456:respawn:/sbin/agetty -L ttyS1 115200 vt100

I've appended the following to my /etc/securetty:
ttyS1

I've created /etc/init/ttyS1.conf which looks like:
start on runlevel [345]
stop on runlevel [S016]

respawn
instance /dev/ttyS1
exec /sbin/agetty ttyS1 115200 vt100

Some concessions:

*

*I'm not exaclty sure which serial port my BIOS are trying to redirect
stuff into (ttyS0, ttyS1). Most of the examples use ttyS1, and since
the grub menu gets redirected there, i'm pretty confident thats
'correct'

*I know the 'terminal types' and baud rates have to match between the
BIOS and OS settings. I am consistently using 115200 for baud, but
i'm less confident I'm choosing the right terminal type. The terminal
type in BIOS is "ANSI", and this gives the coloration i want for the
BIOS over SOL. However, for the OS settings, most of the examples use
'linux'; i'm not sure if that's compatible with my ANSI setting. I've
tried VT100 for both BIOS and OS, and I still never see anything past
the Grub menu (plus, i lose color info for my BIOS over SOL).

Any help is greatly appreciated.

A: I faced similar problem with SOL on Supermicro server (SYS-1028R-WTRT). I used a Centos 7 OS.
I think this sequence of actions help me decide this problem:

*

*I shutdown all systemd getty services (systemctl stop serial-getty@ttyS0 ,  ...ttyS1)

*Manually run /sbin/agetty -L ttyS1 115200 vt100 (this set of parameters get me a login string on SoL connection)

*Kill manually executed agetty.

*In file /etc/default/grub set:
GRUB_CMDLINE_LINUX="console=ttyS1,115200 console=tty0"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=1 --word=8 --parity=no --stop=1"

*grub2-mkconfig -o /boot/grub2/grub.cfg

*Reboot!

After that steps I get working SoL console.

A: What happens on the console once you type the following as root in a shell?:
initctl start serial DEV=TTYS1 SPEED=115200

A: Try to change your console ordering in console=ttyS1,115200n8 console=tty0
If that does not work, maybe the BIOS/Grub and the kernel have different enumeration of the serial port, leading to different numbering.
In this case, try to change your kernel line in console=ttyS0,115200n8 console=tty0

A: I've not used the serial console for sometime but I suspect the issue is the:
rhgb quiet

line in your grub.conf.
This enables the red hat graphical boot.  That will likely corrupt the terminal.
https://access.redhat.com/site/articles/2938

redpajama_set_name: RedPajamaStackExchange


Marvel's cinematic superheroes are cruising towards an existential crisis. Many of their key heroes (from Disney's MCU, Fox's X-Men, and Sony's Spiderverse) are played by aging actors or their current story arcs are reaching logical conclusions. Disney, Marvel, and Fox need to decide (soon) whether these characters are more like James Bond or Luke Skywalker. What does that mean? Consider that seven actors have portrayed James Bond to-date, and the franchise keeps chugging along; by contrast, Mark Hamill is the only actor to have played Luke Skywalker.
By comparison, we've had multiple Spider-Men and Hulks, but only one Wolverine or Iron Man. By emphasizing continuity Marvel's painted themselves into a corner over the last decade and a half. So the big question is: should these studios recast, reassign, or retire any or all of these heroes? In the next couple of years we're going to get some pretty clear evidence how they're leaning, one way or the other.
When Bryan Singer's X-Men debuted in 2000, we were introduced to Hugh Jackman's amazing Wolverine, a career-making role. Arguably, this was the beginning of the modern era of Marvel superhero film (yes, yes, Blade hit in 1998, but X-Men still feels like the beginning to me). Can anyone imagine a non-Jackman Wolverine? All thee Wolverine movies combined have earned $1.4 billion to-date. You'd better believe that Fox wants to take that bet, given the money at stake and the intense fan love for this character — but it's a damned risky move.
Iron Man / Stark / Downey Jr.
Iron Man was a B-list comic book character before RDJ blew us away with his portrayal of Tony Stark in 2008. Similar to Jackman's Wolverine, it's hard to imagine anyone else as Stark/Iron Man. However, in the comics many others have worn the armor (sometimes, the suit is even AI-controlled). Iron Man can exist without Tony Stark, but can Marvel part ways with RDJ?
Stark is central to the MCU, his name and his presence are everywhere. However, RDJ turned 50 a couple years ago — playing the action hero over 50 is tenuous — although as Iron Man he is often depicted via CG (similar to Hulk). It's conceivable that RDJ could continue in the MCU as Stark only, a defacto father figure; perhaps he passes along the Iron Man mantle while he assumes a background supporting or management role. Consequently, RDJ could continue on with the MCU for years as Stark, but maybe it's best to hand off the keys to the suit to a younger protege, which could seriously energize Iron Man 4 (if Marvel decides to go that way).
It took Chris Evans a while to connect with Steve Rogers/Captain America, he even fancied walking away a time or two, but Evans found his footing and his Rogers/Cap has become the moral compass of the MCU, and a great counterpoint and foil to RDJ's Iron Man. However, if you've followed the comics over the last decade you've seen Cap killed, resurrected, live a full life in another dimension, grow old, and even become a Hydra villain — it's been a pretty wild ride. During this time Cap's best buddy, Bucky Barnes, once carried the shield and established a darker and gun-happy version of the Captain America. Sam Wilson's Falcon has also assumed the role, resulting in multiple Captain Americas at various times in the comics.
The interesting thing is, Evans' Rogers is not nearly as important to the MCU as RDJ's Stark. Were Evans to depart, it might not have as large an impact on the storytelling — particularly given the character's history with Wilson and Barnes.
The MCU version of Barnes (Sebastian Stan) appears poised to step into the role, either during or after Avengers: Infinity War — he's earned the shot. However, Falcon (Anthony Mackie) would also be a fantastic choice to pick up the shield, and present a high-flying version of the Sentinel of Liberty. However, we think it's more likely that Barnes' Winter Soldier will complete his redemption story and honor his friend, as there's a very good chance Evans walks into the sunset or (more likely) sacrifices himself to save others as the ultimate heroic gesture in one of the next two Avengers films.


I always thought you just show up and march. I was wrong. Marches are expensive and extremely labor intensive for volunteers. I support Women's March LA because it's the most empowering event I've ever done. It's a platform where we come together as a united front to raise our voice which is undeniably powerful.


Does your garage door need maintenance or repairs?
Searching for spare garage parts? Visit our online store!
Want to shop for spare parts for a garage door from the comfort of your own home? Qualified tradespeople can access exclusive deals when ordering parts direct from our online store! If there's anything we can help you with when choosing a spare part, please don't hesitate to call us on 07 3888 1577 for any questions.


text:
Content Marketing Lessons From the Food Babe
By Annie ZelmMay 11 /2015
As a nutritionist, "Food Babe" Vani Hari's credentials are questionable. She's neither a dietitian nor someone with a health or science background; she's a consultant who came down with appendicitis and decided it must have been a reaction to toxic chemicals in her diet.
So she quit her job and began a crusade against the food industry, demanding companies like Starbucks, Subway and Panera stop using genetically modified ingredients and, in her own words, anything a third-grader can't pronounce.
At best, she's using an aggressive approach in an effort to help people live healthier lives; at worst, her critics say she's a fearmonger spreading lies while growing rich off the sales of her books and her sponsor, Suja, (a juice that has no GMOs but 42 grams of sugar). Yale neurologist Steve Novella has even called her "the Jenny McCarthy of food activism." And others, with the credentials she lacks, have taken her to task recently.
But whether or not Food Babe's warnings have made you think twice before enjoying a Pumpkin Spice Latte (no guilt here), you can't argue her success as a marketer.
Her website had more than 54 million visits last year, and Time Magazine named her among the 30 Most Influential People on the Internet.
So what content marketing lessons can we learn from her? Here are four.
Fear Is A Powerful Motivator
Telling people they're eating poison that could be slowly killing them may not be advisable, but it will certainly get attention. We're all anxious, stressed, frustrated or self-conscious about something. For Food Babe's followers, it's the fact that we don't always know what we're putting into our bodies or feeding our children, a real concern.
The best marketers know how to tap into legitimate concerns and provide a solution that addresses them. If you're the IT director at a large healthcare company, it could be the fear of someone hacking into thousands of patient records, compromising sensitive data. They may be looking for an extra level of security to safeguard that data.
Successful marketers don't have to sound the alarm bells to make their audience listen. They just have to understand their buyers' pain points and write content that makes them feel understood at every stage, whether they are just beginning to search for a solution, weighing several options or clarifying some final questions before making a decision.
Be Helpful and Inspiring
The Food Babe has an entire line of products she endorses in addition to her paid subscriptions and bestselling book, but these aren't the first things most visitors notice when they visit the website.
She opens the conversation with her latest investigations, mostly controversial blog posts, recipes and healthy eating guides. She's giving away as much as she's selling, enticing readers with a large sampling of food-related information before directing them to her book for more.
However, she does more than tell her readers what they should eat and why. She shows them how she looked before she made dramatic changes to her lifestyle and how her appearance has improved since then. She posts photos of healthy meals and recent workouts, giving readers something to aspire to that actually seems attainable.
No matter what they're ultimately selling, every marketer should offer a wide array of content that's both practical and aspirational. For a manufacturing company, that might be a blog or microsite that showcases the latest innovations in the industry through content that may never mention the product. GE's Ideas Lab is a great example of this, highlighting some of the best ideas in transportation, energy, global business and healthcare.
Be Everywhere
Food Babe seems to have mastered the art of spreading her message to the masses. She's been on TV shows including Good Morning America and Dr. Oz, and she's been featured in major publications. She publishes something new almost daily and promotes it heavily on social media. After quitting her corporate job, she devoted herself full-time to contacting companies, meeting with consumer organizations, attending trade shows and writing about all of it. In short, she put herself on the map.
Sure, taking on Subway and other huge corporations while rubbing elbows with Michelle Obama on occasion certainly helped. But the reality is, building a brand through content requires a dedicated effort.
There's a common saying among content marketers: Blog as often as you want to be found. In fact, 82 percent of companies that blog daily acquired a customer directly from their blog, according to HubSpot's 2013 State of Inbound Marketing report. But even those that blogged at least once a month are still seeing impressive results; 57 percent of those companies also acquired a customer from the blog.
That's why many companies are hiring their own dedicated writers, designers, videographers and social media managers. Others are hiring skilled freelancers or a content marketing agency to fill the void.
While blogging, email marketing, social media and other inbound marketing tactics are vital to growing your presence online, marketers cannot ignore traditional outbound tactics as a means of promoting all the content they are creating. Looking for creative opportunities to generate demand through advertising and PR should also be part of the strategy.
Recruit An Army of Loyal Followers
If there's one thing Food Babe has done better than perhaps anything else, it's recruiting a following of devoted fans who will spread her message. She's captured the attention of other food bloggers and advocates with influence who are willing to promote her on their own websites.
She has created a popular hashtag, #FoodBabeArmy, to recruit and encourage others to take a stand. Upon a recent announcement from Panera Bread, she posted, "Because of you, Panera Bread is removing 150 additives."
She's good at this key to successful marketing: Finding influencers in the blogosphere and beyond who can make your content more visible.
Marketers should spend time identifying these influencers in their sphere and building relationships with them on social media, at trade shows and elsewhere. One way to do this is by creating seed content, or content potential influencers are likely to share because it includes them. A top 10 list of the most influential people or companies within your industry is one example.
The Food Babe's credibility issues and the controversy she's generated cannot be overlooked, but neither can her influence. No matter what their industry, marketers can learn from her success in building a brand and saturating the Internet.
And no matter what we think of her, it has made her rich. Need more proof to show content marketing ROI and how to measure it? Check out our eBook, and let us know what you think of the Food Babe's marketing tactics.
Annie Zelm
As the content manager, Annie manages a team of brand journalists and is the driving force behind the content strategy for companies in a wide range of industries, including healthcare, technology and professional services. Relying on interviewing skills she developed in her seven years as a journalist, she uncovers insights about what motivates buyers in these industries and uses that knowledge to shape client websites and editorial calendars.
SEO, Content and Design
Blogging for SEO: The Checklist Every Writer Needs
Enterprise SEO: A Simple (But Complete) Guide
4 Ways to Optimize B2B Content for a Mobile-First Experience


text:
Nemopistha hennini is een insect uit de familie van de Nemopteridae, die tot de orde netvleugeligen (Neuroptera) behoort.

Nemopistha hennini is voor het eerst wetenschappelijk beschreven door Navás in 1911.

Nemopteridae

redpajama_set_name: RedPajamaWikipedia


text:
package org.apache.beam.sdk.io.aws2.sqs;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Preconditions.checkState;
import static software.amazon.awssdk.services.sqs.model.QueueAttributeName.VISIBILITY_TIMEOUT;

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.beam.sdk.io.UnboundedSource;
import org.apache.beam.sdk.io.UnboundedSource.CheckpointMark;
import org.apache.beam.sdk.transforms.Combine;
import org.apache.beam.sdk.transforms.Sum;
import org.apache.beam.sdk.transforms.windowing.BoundedWindow;
import org.apache.beam.sdk.util.BucketingFunction;
import org.apache.beam.sdk.util.MovingFunction;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Iterables;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Lists;
import org.joda.time.Duration;
import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.BatchResultErrorEntry;
import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityBatchRequest;
import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityBatchRequestEntry;
import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityBatchResponse;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequestEntry;
import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchResponse;
import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest;
import software.amazon.awssdk.services.sqs.model.Message;
import software.amazon.awssdk.services.sqs.model.MessageSystemAttributeName;
import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse;

@SuppressWarnings({
  "nullness" // TODO(https://issues.apache.org/jira/browse/BEAM-10402)
})
class SqsUnboundedReader extends UnboundedSource.UnboundedReader<SqsMessage> {
  private static final Logger LOG = LoggerFactory.getLogger(SqsUnboundedReader.class);

  /** Maximum number of messages to pull from SQS per request. */
  public static final int MAX_NUMBER_OF_MESSAGES = 10;

  /** Maximum times to retry batch SQS operations upon partial success. */
  private static final int BATCH_OPERATION_MAX_RETIRES = 5;

  /** Timeout for round trip from receiving a message to finally deleting it from SQS. */
  private static final Duration PROCESSING_TIMEOUT = Duration.standardMinutes(2);

  /**
   * Percentage of visibility timeout by which to extend visibility timeout when they are near
   * timeout.
   */
  private static final int VISIBILITY_EXTENSION_PCT = 50;

  /**
   * Percentage of ack timeout we should use as a safety margin. We'll try to extend visibility
   * timeout by this margin before the visibility timeout actually expires.
   */
  private static final int VISIBILITY_SAFETY_PCT = 20;

  /**
   * For stats only: How close we can get to an visibility deadline before we risk it being already
   * considered passed by SQS.
   */
  private static final Duration VISIBILITY_TOO_LATE = Duration.standardSeconds(2);

  /** Maximum number of message ids per delete or visibility extension call. */
  private static final int DELETE_BATCH_SIZE = 10;

  /** Maximum number of messages in flight. */
  private static final int MAX_IN_FLIGHT = 20000;

  /** Period of samples to determine watermark and other stats. */
  private static final Duration SAMPLE_PERIOD = Duration.standardMinutes(1);

  /** Period of updates to determine watermark and other stats. */
  private static final Duration SAMPLE_UPDATE = Duration.standardSeconds(5);

  /** Period for logging stats. */
  private static final Duration LOG_PERIOD = Duration.standardSeconds(30);

  /** Minimum number of unread messages required before considering updating watermark. */
  private static final int MIN_WATERMARK_MESSAGES = 10;

  /**
   * Minimum number of SAMPLE_UPDATE periods over which unread messages should be spread before
   * considering updating watermark.
   */
  private static final int MIN_WATERMARK_SPREAD = 2;

  // TODO: Would prefer to use MinLongFn but it is a BinaryCombineFn<Long> rather
  // than a BinaryCombineLongFn. [BEAM-285]
  private static final Combine.BinaryCombineLongFn MIN =
      new Combine.BinaryCombineLongFn() {
        @Override
        public long apply(long left, long right) {
          return Math.min(left, right);
        }

        @Override
        public long identity() {
          return Long.MAX_VALUE;
        }
      };

  private static final Combine.BinaryCombineLongFn MAX =
      new Combine.BinaryCombineLongFn() {
        @Override
        public long apply(long left, long right) {
          return Math.max(left, right);
        }

        @Override
        public long identity() {
          return Long.MIN_VALUE;
        }
      };

  private static final Combine.BinaryCombineLongFn SUM = Sum.ofLongs();

  /** For access to topic and SQS client. */
  private final SqsUnboundedSource source;

  /**
   * The closed state of this {@link SqsUnboundedReader}. If true, the reader has not yet been
   * closed, and it will have a non-null value within {@link #SqsUnboundedReader}.
   */
  private AtomicBoolean active = new AtomicBoolean(true);

  /** The current message, or {@literal null} if none. */
  private SqsMessage current;

  /**
   * Messages we have received from SQS and not yet delivered downstream. We preserve their order.
   */
  private final Queue<SqsMessage> messagesNotYetRead;

  /** Message ids of messages we have delivered downstream but not yet deleted. */
  private Set<String> safeToDeleteIds;

  /**
   * Visibility timeout, in ms, as set on subscription when we first start reading. Not updated
   * thereafter. -1 if not yet determined.
   */
  private long visibilityTimeoutMs;

  /** Byte size of undecoded elements in {@link #messagesNotYetRead}. */
  private long notYetReadBytes;

  /**
   * Bucketed map from received time (as system time, ms since epoch) to message timestamps (mssince
   * epoch) of all received but not-yet read messages. Used to estimate watermark.
   */
  private BucketingFunction minUnreadTimestampMsSinceEpoch;

  /**
   * Minimum of timestamps (ms since epoch) of all recently read messages. Used to estimate
   * watermark.
   */
  private MovingFunction minReadTimestampMsSinceEpoch;

  private static class InFlightState {
    /** Receipt handle of message. */
    String receiptHandle;

    /** When request which yielded message was issued. */
    long requestTimeMsSinceEpoch;

    /**
     * When SQS will consider this message's visibility timeout to timeout and thus it needs to be
     * extended.
     */
    long visibilityDeadlineMsSinceEpoch;

    public InFlightState(
        String receiptHandle, long requestTimeMsSinceEpoch, long visibilityDeadlineMsSinceEpoch) {
      this.receiptHandle = receiptHandle;
      this.requestTimeMsSinceEpoch = requestTimeMsSinceEpoch;
      this.visibilityDeadlineMsSinceEpoch = visibilityDeadlineMsSinceEpoch;
    }
  }

  /**
   * Map from message ids of messages we have received from SQS but not yet deleted to their in
   * flight state. Ordered from earliest to latest visibility deadline.
   */
  private final LinkedHashMap<String, InFlightState> inFlight;

  /**
   * Batches of successfully deleted message ids which need to be pruned from the above. CAUTION:
   * Accessed by both reader and checkpointing threads.
   */
  private final Queue<List<String>> deletedIds;

  /**
   * System time (ms since epoch) we last received a message from SQS, or -1 if not yet received any
   * messages.
   */
  private long lastReceivedMsSinceEpoch;

  /** The last reported watermark (ms since epoch), or beginning of time if none yet reported. */
  private long lastWatermarkMsSinceEpoch;

  /** Stats only: System time (ms since epoch) we last logs stats, or -1 if never. */
  private long lastLogTimestampMsSinceEpoch;

  /** Stats only: Total number of messages received. */
  private long numReceived;

  /** Stats only: Number of messages which have recently been received. */
  private MovingFunction numReceivedRecently;

  /** Stats only: Number of messages which have recently had their deadline extended. */
  private MovingFunction numExtendedDeadlines;

  /**
   * Stats only: Number of messages which have recently had their deadline extended even though it
   * may be too late to do so.
   */
  private MovingFunction numLateDeadlines;

  /** Stats only: Number of messages which have recently been deleted. */
  private MovingFunction numDeleted;

  /**
   * Stats only: Number of messages which have recently expired (visibility timeout were extended
   * for too long).
   */
  private MovingFunction numExpired;

  /** Stats only: Number of messages which have recently been returned to visible on SQS. */
  private MovingFunction numReleased;

  /** Stats only: Number of message bytes which have recently been read by downstream consumer. */
  private MovingFunction numReadBytes;

  /**
   * Stats only: Minimum of timestamp (ms since epoch) of all recently received messages. Used to
   * estimate timestamp skew. Does not contribute to watermark estimator.
   */
  private MovingFunction minReceivedTimestampMsSinceEpoch;

  /**
   * Stats only: Maximum of timestamp (ms since epoch) of all recently received messages. Used to
   * estimate timestamp skew.
   */
  private MovingFunction maxReceivedTimestampMsSinceEpoch;

  /** Stats only: Minimum of recent estimated watermarks (ms since epoch). */
  private MovingFunction minWatermarkMsSinceEpoch;

  /** Stats ony: Maximum of recent estimated watermarks (ms since epoch). */
  private MovingFunction maxWatermarkMsSinceEpoch;

  /**
   * Stats only: Number of messages with timestamps strictly behind the estimated watermark at the
   * time they are received. These may be considered 'late' by downstream computations.
   */
  private MovingFunction numLateMessages;

  /**
   * Stats only: Current number of checkpoints in flight. CAUTION: Accessed by both checkpointing
   * and reader threads.
   */
  AtomicInteger numInFlightCheckpoints;

  /** Stats only: Maximum number of checkpoints in flight at any time. */
  private int maxInFlightCheckpoints;

  private static MovingFunction newFun(Combine.BinaryCombineLongFn function) {
    return new MovingFunction(
        SAMPLE_PERIOD.getMillis(),
        SAMPLE_UPDATE.getMillis(),
        MIN_WATERMARK_SPREAD,
        MIN_WATERMARK_MESSAGES,
        function);
  }

  public SqsUnboundedReader(SqsUnboundedSource source, SqsCheckpointMark sqsCheckpointMark)
      throws IOException {
    this.source = source;

    messagesNotYetRead = new ArrayDeque<>();
    safeToDeleteIds = new HashSet<>();
    inFlight = new LinkedHashMap<>();
    deletedIds = new ConcurrentLinkedQueue<>();
    visibilityTimeoutMs = -1;
    notYetReadBytes = 0;
    minUnreadTimestampMsSinceEpoch =
        new BucketingFunction(
            SAMPLE_UPDATE.getMillis(), MIN_WATERMARK_SPREAD, MIN_WATERMARK_MESSAGES, MIN);
    minReadTimestampMsSinceEpoch = newFun(MIN);
    lastReceivedMsSinceEpoch = -1;
    lastWatermarkMsSinceEpoch = BoundedWindow.TIMESTAMP_MIN_VALUE.getMillis();
    current = null;
    lastLogTimestampMsSinceEpoch = -1;
    numReceived = 0L;
    numReceivedRecently = newFun(SUM);
    numExtendedDeadlines = newFun(SUM);
    numLateDeadlines = newFun(SUM);
    numDeleted = newFun(SUM);
    numExpired = newFun(SUM);
    numReleased = newFun(SUM);
    numReadBytes = newFun(SUM);
    minReceivedTimestampMsSinceEpoch = newFun(MIN);
    maxReceivedTimestampMsSinceEpoch = newFun(MAX);
    minWatermarkMsSinceEpoch = newFun(MIN);
    maxWatermarkMsSinceEpoch = newFun(MAX);
    numLateMessages = newFun(SUM);
    numInFlightCheckpoints = new AtomicInteger();
    maxInFlightCheckpoints = 0;

    if (sqsCheckpointMark != null) {
      long nowMsSinceEpoch = now();
      extendBatch(nowMsSinceEpoch, sqsCheckpointMark.notYetReadReceipts, 0);
      numReleased.add(nowMsSinceEpoch, sqsCheckpointMark.notYetReadReceipts.size());
    }
  }

  @Override
  public Instant getWatermark() {

    // NOTE: We'll allow the watermark to go backwards. The underlying runner is responsible
    // for aggregating all reported watermarks and ensuring the aggregate is latched.
    // If we attempt to latch locally then it is possible a temporary starvation of one reader
    // could cause its estimated watermark to fast forward to current system time. Then when
    // the reader resumes its watermark would be unable to resume tracking.
    // By letting the underlying runner latch we avoid any problems due to localized starvation.
    long nowMsSinceEpoch = now();
    long readMin = minReadTimestampMsSinceEpoch.get(nowMsSinceEpoch);
    long unreadMin = minUnreadTimestampMsSinceEpoch.get();
    if (readMin == Long.MAX_VALUE
        && unreadMin == Long.MAX_VALUE
        && lastReceivedMsSinceEpoch >= 0
        && nowMsSinceEpoch > lastReceivedMsSinceEpoch + SAMPLE_PERIOD.getMillis()) {
      // We don't currently have any unread messages pending, we have not had any messages
      // read for a while, and we have not received any new messages from SQS for a while.
      // Advance watermark to current time.
      // TODO: Estimate a timestamp lag.
      lastWatermarkMsSinceEpoch = nowMsSinceEpoch;
    } else if (minReadTimestampMsSinceEpoch.isSignificant()
        || minUnreadTimestampMsSinceEpoch.isSignificant()) {
      // Take minimum of the timestamps in all unread messages and recently read messages.
      lastWatermarkMsSinceEpoch = Math.min(readMin, unreadMin);
    }
    // else: We're not confident enough to estimate a new watermark. Stick with the old one.
    minWatermarkMsSinceEpoch.add(nowMsSinceEpoch, lastWatermarkMsSinceEpoch);
    maxWatermarkMsSinceEpoch.add(nowMsSinceEpoch, lastWatermarkMsSinceEpoch);
    return new Instant(lastWatermarkMsSinceEpoch);
  }

  @Override
  public SqsMessage getCurrent() throws NoSuchElementException {
    if (current == null) {
      throw new NoSuchElementException();
    }
    return current;
  }

  @Override
  public Instant getCurrentTimestamp() throws NoSuchElementException {
    if (current == null) {
      throw new NoSuchElementException();
    }

    return getTimestamp(current.getTimeStamp());
  }

  @Override
  public byte[] getCurrentRecordId() throws NoSuchElementException {
    if (current == null) {
      throw new NoSuchElementException();
    }
    return current.getMessageId().getBytes(UTF_8);
  }

  @Override
  public CheckpointMark getCheckpointMark() {
    int cur = numInFlightCheckpoints.incrementAndGet();
    maxInFlightCheckpoints = Math.max(maxInFlightCheckpoints, cur);
    List<String> snapshotSafeToDeleteIds = Lists.newArrayList(safeToDeleteIds);
    List<String> snapshotNotYetReadReceipts = new ArrayList<>(messagesNotYetRead.size());
    for (SqsMessage message : messagesNotYetRead) {
      snapshotNotYetReadReceipts.add(message.getReceiptHandle());
    }
    return new SqsCheckpointMark(this, snapshotSafeToDeleteIds, snapshotNotYetReadReceipts);
  }

  @Override
  public SqsUnboundedSource getCurrentSource() {
    return source;
  }

  @Override
  public boolean start() throws IOException {
    visibilityTimeoutMs =
        Integer.parseInt(
                source
                    .getSqs()
                    .getQueueAttributes(
                        GetQueueAttributesRequest.builder()
                            .queueUrl(source.getRead().queueUrl())
                            .attributeNames(VISIBILITY_TIMEOUT)
                            .build())
                    .attributes()
                    .get(VISIBILITY_TIMEOUT))
            * 1000L;
    return advance();
  }

  @Override
  public boolean advance() throws IOException {
    // Emit stats.
    stats();

    if (current != null) {
      // Current is consumed. It can no longer contribute to holding back the watermark.
      minUnreadTimestampMsSinceEpoch.remove(Long.parseLong(current.getRequestTimeStamp()));
      current = null;
    }

    // Retire state associated with deleted messages.
    retire();

    // Extend all pressing deadlines.
    // Will BLOCK until done.
    // If the system is pulling messages only to let them sit in a downstream queue then
    // this will have the effect of slowing down the pull rate.
    // However, if the system is genuinely taking longer to process each message then
    // the work to extend visibility timeout would be better done in the background.
    extend();

    if (messagesNotYetRead.isEmpty()) {
      // Pull another batch.
      // Will BLOCK until fetch returns, but will not block until a message is available.
      pull();
    }

    // Take one message from queue.
    current = messagesNotYetRead.poll();
    if (current == null) {
      // Try again later.
      return false;
    }
    notYetReadBytes -= current.getBody().getBytes(UTF_8).length;
    checkState(notYetReadBytes >= 0);
    long nowMsSinceEpoch = now();
    numReadBytes.add(nowMsSinceEpoch, current.getBody().getBytes(UTF_8).length);
    minReadTimestampMsSinceEpoch.add(nowMsSinceEpoch, getCurrentTimestamp().getMillis());
    ;
    if (getCurrentTimestamp().getMillis() < lastWatermarkMsSinceEpoch) {
      numLateMessages.add(nowMsSinceEpoch, 1L);
    }

    // Current message can be considered 'read' and will be persisted by the next
    // checkpoint. So it is now safe to delete from SQS.
    safeToDeleteIds.add(current.getMessageId());

    return true;
  }

  /**
   * {@inheritDoc}.
   *
   *
Marks this {@link SqsUnboundedReader} as no longer active. The {@link SqsClient} continue to
   * exist and be active beyond the life of this call if there are any in-flight checkpoints. When
   * no in-flight checkpoints remain, the reader will be closed.
   */
  @Override
  public void close() throws IOException {
    active.set(false);
    maybeCloseClient();
  }

  /**
   * Close this reader's underlying {@link SqsClient} if the reader has been closed and there are no
   * outstanding checkpoints.
   */
  void maybeCloseClient() throws IOException {
    if (!active.get() && numInFlightCheckpoints.get() == 0) {
      // The reader has been closed and it has no more outstanding checkpoints. The client
      // must be closed so it doesn't leak
      SqsClient client = source.getSqs();
      if (client != null) {
        client.close();
      }
    }
  }

  /** delete the provided {@code messageIds} from SQS. */
  void delete(List<String> messageIds) throws IOException {
    AtomicInteger counter = new AtomicInteger();
    for (List<String> messageList :
        messageIds.stream()
            .collect(groupingBy(x -> counter.getAndIncrement() / DELETE_BATCH_SIZE))
            .values()) {
      deleteBatch(messageList);
    }
  }

  /**
   * delete the provided {@code messageIds} from SQS, blocking until all of the messages are
   * deleted.
   *
   *
CAUTION: May be invoked from a separate thread.
   *
   *
CAUTION: Retains {@code messageIds}.
   */
  private void deleteBatch(List<String> messageIds) throws IOException {
    int retries = 0;
    Map<String, String> pendingReceipts =
        IntStream.range(0, messageIds.size())
            .boxed()
            .filter(i -> inFlight.containsKey(messageIds.get(i)))
            .collect(toMap(Object::toString, i -> inFlight.get(messageIds.get(i)).receiptHandle));

    while (!pendingReceipts.isEmpty()) {

      if (retries >= BATCH_OPERATION_MAX_RETIRES) {
        throw new IOException(
            "Failed to extend visibility timeout for "
                + pendingReceipts.size()
                + " messages after "
                + retries
                + " retries");
      }

      List<DeleteMessageBatchRequestEntry> entries =
          pendingReceipts.entrySet().stream()
              .map(
                  r ->
                      DeleteMessageBatchRequestEntry.builder()
                          .id(r.getKey())
                          .receiptHandle(r.getValue())
                          .build())
              .collect(Collectors.toList());

      DeleteMessageBatchResponse result =
          source
              .getSqs()
              .deleteMessageBatch(
                  DeleteMessageBatchRequest.builder()
                      .queueUrl(source.getRead().queueUrl())
                      .entries(entries)
                      .build());

      // Reflect failed message IDs to map
      pendingReceipts
          .keySet()
          .retainAll(
              result.failed().stream().map(BatchResultErrorEntry::id).collect(Collectors.toSet()));

      retries += 1;
    }
    deletedIds.add(messageIds);
  }

  /**
   * Messages which have been deleted (via the checkpoint finalize) are no longer in flight. This is
   * only used for flow control and stats.
   */
  private void retire() {
    long nowMsSinceEpoch = now();
    while (true) {
      List<String> ackIds = deletedIds.poll();
      if (ackIds == null) {
        return;
      }
      numDeleted.add(nowMsSinceEpoch, ackIds.size());
      for (String ackId : ackIds) {
        inFlight.remove(ackId);
        safeToDeleteIds.remove(ackId);
      }
    }
  }

  /** BLOCKING Fetch another batch of messages from SQS. */
  private void pull() {
    if (inFlight.size() >= MAX_IN_FLIGHT) {
      // Wait for checkpoint to be finalized before pulling anymore.
      // There may be lag while checkpoints are persisted and the finalizeCheckpoint method
      // is invoked. By limiting the in-flight messages we can ensure we don't end up consuming
      // messages faster than we can checkpoint them.
      return;
    }

    long requestTimeMsSinceEpoch = now();
    long deadlineMsSinceEpoch = requestTimeMsSinceEpoch + visibilityTimeoutMs;

    final ReceiveMessageRequest receiveMessageRequest =
        ReceiveMessageRequest.builder()
            .maxNumberOfMessages(MAX_NUMBER_OF_MESSAGES)
            .attributeNamesWithStrings(MessageSystemAttributeName.SENT_TIMESTAMP.toString())
            .queueUrl(source.getRead().queueUrl())
            .build();

    final ReceiveMessageResponse receiveMessageResponse =
        source.getSqs().receiveMessage(receiveMessageRequest);

    final List<Message> messages = receiveMessageResponse.messages();

    if (messages == null || messages.isEmpty()) {
      return;
    }

    lastReceivedMsSinceEpoch = requestTimeMsSinceEpoch;

    // Capture the received messages.
    for (Message orgMsg : messages) {
      String timeStamp = orgMsg.attributes().get(MessageSystemAttributeName.SENT_TIMESTAMP);
      String requestTimeStamp = Long.toString(requestTimeMsSinceEpoch);
      SqsMessage message =
          SqsMessage.create(
              orgMsg.body(),
              orgMsg.messageId(),
              orgMsg.receiptHandle(),
              timeStamp,
              requestTimeStamp);
      messagesNotYetRead.add(message);
      notYetReadBytes += message.getBody().getBytes(UTF_8).length;
      inFlight.put(
          message.getMessageId(),
          new InFlightState(
              message.getReceiptHandle(), requestTimeMsSinceEpoch, deadlineMsSinceEpoch));
      numReceived++;
      numReceivedRecently.add(requestTimeMsSinceEpoch, 1L);
      minReceivedTimestampMsSinceEpoch.add(
          requestTimeMsSinceEpoch, getTimestamp(message.getTimeStamp()).getMillis());
      maxReceivedTimestampMsSinceEpoch.add(
          requestTimeMsSinceEpoch, getTimestamp(message.getTimeStamp()).getMillis());
      minUnreadTimestampMsSinceEpoch.add(
          requestTimeMsSinceEpoch, getTimestamp(message.getTimeStamp()).getMillis());
    }
  }

  /** Return the current time, in ms since epoch. */
  long now() {
    return System.currentTimeMillis();
  }

  /**
   * BLOCKING Extend deadline for all messages which need it. CAUTION: If extensions can't keep up
   * with wallclock then we'll never return.
   */
  private void extend() throws IOException {
    while (true) {
      long nowMsSinceEpoch = now();
      List<String> assumeExpired = new ArrayList<>();
      List<String> toBeExtended = new ArrayList<>();
      List<String> toBeExpired = new ArrayList<>();
      // Messages will be in increasing deadline order.
      for (Map.Entry<String, InFlightState> entry : inFlight.entrySet()) {
        if (entry.getValue().visibilityDeadlineMsSinceEpoch
                - (visibilityTimeoutMs * VISIBILITY_SAFETY_PCT) / 100
            > nowMsSinceEpoch) {
          // All remaining messages don't need their visibility timeouts to be extended.
          break;
        }

        if (entry.getValue().visibilityDeadlineMsSinceEpoch - VISIBILITY_TOO_LATE.getMillis()
            < nowMsSinceEpoch) {
          // SQS may have already considered this message to have expired.
          // If so it will (eventually) be made available on a future pull request.
          // If this message ends up being committed then it will be considered a duplicate
          // when re-pulled.
          assumeExpired.add(entry.getKey());
          continue;
        }

        if (entry.getValue().requestTimeMsSinceEpoch + PROCESSING_TIMEOUT.getMillis()
            < nowMsSinceEpoch) {
          // This message has been in-flight for too long.
          // Give up on it, otherwise we risk extending its visibility timeout indefinitely.
          toBeExpired.add(entry.getKey());
          continue;
        }

        // Extend the visibility timeout for this message.
        toBeExtended.add(entry.getKey());
        if (toBeExtended.size() >= DELETE_BATCH_SIZE) {
          // Enough for one batch.
          break;
        }
      }

      if (assumeExpired.isEmpty() && toBeExtended.isEmpty() && toBeExpired.isEmpty()) {
        // Nothing to be done.
        return;
      }

      if (!assumeExpired.isEmpty()) {
        // If we didn't make the visibility deadline assume expired and no longer in flight.
        numLateDeadlines.add(nowMsSinceEpoch, assumeExpired.size());
        for (String messageId : assumeExpired) {
          inFlight.remove(messageId);
        }
      }

      if (!toBeExpired.isEmpty()) {
        // Expired messages are no longer considered in flight.
        numExpired.add(nowMsSinceEpoch, toBeExpired.size());
        for (String messageId : toBeExpired) {
          inFlight.remove(messageId);
        }
      }

      if (!toBeExtended.isEmpty()) {
        // SQS extends visibility timeout from it's notion of current time.
        // We'll try to track that on our side, but note the deadlines won't necessarily agree.
        long extensionMs = (int) ((visibilityTimeoutMs * VISIBILITY_EXTENSION_PCT) / 100L);
        long newDeadlineMsSinceEpoch = nowMsSinceEpoch + extensionMs;
        for (String messageId : toBeExtended) {
          // Maintain increasing ack deadline order.
          String receiptHandle = inFlight.get(messageId).receiptHandle;
          InFlightState state = inFlight.remove(messageId);
          inFlight.put(
              messageId,
              new InFlightState(
                  receiptHandle, state.requestTimeMsSinceEpoch, newDeadlineMsSinceEpoch));
        }
        List<String> receiptHandles =
            toBeExtended.stream()
                .map(inFlight::get)
                .filter(Objects::nonNull) // get rid of null values
                .map(m -> m.receiptHandle)
                .collect(Collectors.toList());
        // BLOCKs until extended.
        extendBatch(nowMsSinceEpoch, receiptHandles, (int) (extensionMs / 1000));
      }
    }
  }

  /**
   * BLOCKING Extend the visibility timeout for messages from SQS with the given {@code
   * receiptHandles}.
   */
  void extendBatch(long nowMsSinceEpoch, List<String> receiptHandles, int extensionSec)
      throws IOException {
    int retries = 0;
    int numMessages = receiptHandles.size();
    Map<String, String> pendingReceipts =
        IntStream.range(0, receiptHandles.size())
            .boxed()
            .collect(toMap(Object::toString, receiptHandles::get));

    while (!pendingReceipts.isEmpty()) {

      if (retries >= BATCH_OPERATION_MAX_RETIRES) {
        throw new IOException(
            "Failed to extend visibility timeout for "
                + receiptHandles.size()
                + " messages after "
                + retries
                + " retries");
      }

      List<ChangeMessageVisibilityBatchRequestEntry> entries =
          pendingReceipts.entrySet().stream()
              .map(
                  r ->
                      ChangeMessageVisibilityBatchRequestEntry.builder()
                          .id(r.getKey())
                          .receiptHandle(r.getValue())
                          .visibilityTimeout(extensionSec)
                          .build())
              .collect(Collectors.toList());

      ChangeMessageVisibilityBatchResponse response =
          source
              .getSqs()
              .changeMessageVisibilityBatch(
                  ChangeMessageVisibilityBatchRequest.builder()
                      .queueUrl(source.getRead().queueUrl())
                      .entries(entries)
                      .build());

      pendingReceipts
          .keySet()
          .retainAll(
              response.failed().stream()
                  .map(BatchResultErrorEntry::id)
                  .collect(Collectors.toSet()));

      retries += 1;
    }
    numExtendedDeadlines.add(nowMsSinceEpoch, numMessages);
  }

  /** Log stats if time to do so. */
  private void stats() {
    long nowMsSinceEpoch = now();
    if (lastLogTimestampMsSinceEpoch < 0) {
      lastLogTimestampMsSinceEpoch = nowMsSinceEpoch;
      return;
    }
    long deltaMs = nowMsSinceEpoch - lastLogTimestampMsSinceEpoch;
    if (deltaMs < LOG_PERIOD.getMillis()) {
      return;
    }

    String messageSkew = "unknown";
    long minTimestamp = minReceivedTimestampMsSinceEpoch.get(nowMsSinceEpoch);
    long maxTimestamp = maxReceivedTimestampMsSinceEpoch.get(nowMsSinceEpoch);
    if (minTimestamp < Long.MAX_VALUE && maxTimestamp > Long.MIN_VALUE) {
      messageSkew = (maxTimestamp - minTimestamp) + "ms";
    }

    String watermarkSkew = "unknown";
    long minWatermark = minWatermarkMsSinceEpoch.get(nowMsSinceEpoch);
    long maxWatermark = maxWatermarkMsSinceEpoch.get(nowMsSinceEpoch);
    if (minWatermark < Long.MAX_VALUE && maxWatermark > Long.MIN_VALUE) {
      watermarkSkew = (maxWatermark - minWatermark) + "ms";
    }

    String oldestInFlight = "no";
    String oldestAckId = Iterables.getFirst(inFlight.keySet(), null);
    if (oldestAckId != null) {
      oldestInFlight = (nowMsSinceEpoch - inFlight.get(oldestAckId).requestTimeMsSinceEpoch) + "ms";
    }

    LOG.info(
        "SQS {} has "
            + "{} received messages, "
            + "{} current unread messages, "
            + "{} current unread bytes, "
            + "{} current in-flight msgs, "
            + "{} oldest in-flight, "
            + "{} current in-flight checkpoints, "
            + "{} max in-flight checkpoints, "
            + "{}B/s recent read, "
            + "{} recent received, "
            + "{} recent extended, "
            + "{} recent late extended, "
            + "{} recent deleted, "
            + "{} recent released, "
            + "{} recent expired, "
            + "{} recent message timestamp skew, "
            + "{} recent watermark skew, "
            + "{} recent late messages, "
            + "{} last reported watermark, "
            + "{} min recent read timestamp (significance = {}), "
            + "{} min recent unread timestamp (significance = {}), "
            + "{} last receive timestamp",
        source.getRead().queueUrl(),
        numReceived,
        messagesNotYetRead.size(),
        notYetReadBytes,
        inFlight.size(),
        oldestInFlight,
        numInFlightCheckpoints.get(),
        maxInFlightCheckpoints,
        numReadBytes.get(nowMsSinceEpoch) / (SAMPLE_PERIOD.getMillis() / 1000L),
        numReceivedRecently.get(nowMsSinceEpoch),
        numExtendedDeadlines.get(nowMsSinceEpoch),
        numLateDeadlines.get(nowMsSinceEpoch),
        numDeleted.get(nowMsSinceEpoch),
        numReleased.get(nowMsSinceEpoch),
        numExpired.get(nowMsSinceEpoch),
        messageSkew,
        watermarkSkew,
        numLateMessages.get(nowMsSinceEpoch),
        new Instant(lastWatermarkMsSinceEpoch),
        new Instant(minReadTimestampMsSinceEpoch.get(nowMsSinceEpoch)),
        minReadTimestampMsSinceEpoch.isSignificant(),
        new Instant(minUnreadTimestampMsSinceEpoch.get()),
        minUnreadTimestampMsSinceEpoch.isSignificant(),
        new Instant(lastReceivedMsSinceEpoch));

    lastLogTimestampMsSinceEpoch = nowMsSinceEpoch;
  }

  private Instant getTimestamp(String timeStamp) {
    return new Instant(Long.parseLong(timeStamp));
  }
}