text:
VYPE Class 6A Helmet Stickers powered by Houston Methodist Orthopedics & Sports Medicine: Week 9 (Nov. 19-21)
November 25, 2020 [email protected]_84 Class, Helmet, Houston, medicine, Methodist, Nov, Orthopedics, powered, sports, Stickers, VYPE, Week
Welcome to a new VYPE feature for the 2020 football season – VYPE Helmet Stickers powered by Houston Methodist Orthopedics & Sports Medicine! Every week, VYPE will scour the stat sheets of the previous week and find the top performers.
Class 6A teams went into Week 9 and wow there were some amazing performances! See who earned VYPE Helmet Stickers this week. Here are the selections
PREVIOUS HELMET STICKER SELECTIONS
– Week 1 (Sept. 24-27)
– Week 2 (Oct. 1-3)
– Week 3 (Oct. 8-10)
– Week 4 (Oct. 15-17)
– Week 7 (Nov. 3-5
– Week 8 (Nov. 12-14)
Carter Brown (@CarterABrown) – Pearland Dawson
Let's lead this thing off with a kicker! In the epic District 23-6A showdown last week at Freedom Field, it went to overtime between Shadow Creek and Pearland Dawson. After a turnover on its first drive of overtime, Pearland Dawson had a chance to win the game. They got in field goal range and called on All-State kicker Carter Brown. He trotted out and nailed a 23-yard game-winning field goal to clinch the District 23-6A Championship for the Eagles and second-ever undefeated regular season. He also went 4 of 4 in extra point attempts in the game as well.
Daelyn Williams (@sirpaydae) – Dekaney
Dekaney improved to 3-0 in district play after a 52-7 win over Eisenhower last week. The Wildcats' offense was paced by Daelyn Williams finished 10 of 14 for 184 yards and three touchdowns. It was a nice win for Dekaney.
Charles Garrett (@3way_tank) – Klein Oak
In a tight 21-14 win over Klein last week, Klein Oak running back Charles Garrett had a nice afternoon. Garrett finished the game rushing for 143 yards and a score on 18 carries. Nice game for the junior back for the Panthers.
Colton Marwill (@CMarwill) – Tomball Memorial
It took a thrilling 49-48 overtime victory over Klein Collins to remain perfect but Tomball Memorial was able to do just that. Colton Marwill has returned at QB after being held out a few weeks due to injury. Marwill looks fully healthy again as he finished 20 of 32 for 328 yards and four touchdowns with two interceptions. Marwill also rushed for another 37 yards.
Cy Park Team!
Extremely proud of these players, coaches, and trainers for all the work they've put in to get to this point. Battled adversity to make history! I think we got our swagger back… pic.twitter.com/kxLE8s2glE
— Casey Rosellini (@CoachRosellini) November 21, 2020
We are giving a helmet sticker to the ENTIRE Cy Park football team!! That's what you get when you make history. Last week a 42-29 win over Langham Creek punched the Tigers' ticket to the 2020 playoffs. It is the first time in program history that Cy Park is heading to the playoffs. Some individual performances did stand out. The Tigers only had five yards passing for the game but then ran the ball for 475 yards. That's
Inspired by Her Cancer Struggle, Kan. Teacher's Class Brings Holiday Cheer to Pediatric Patients
October 28, 2020 [email protected]_84 Brings, Cancer, Cheer, Class, holiday, Inspired, Kan, Patients, Pediatric, Struggle, teachers
Angela Holtgraves' special education students began the Stocking Project in 2017 upon learning of Holtgraves' own cancer battle
When the holiday season rolls around, hundreds of pediatric cancer patients in Kansas will receive stockings stuffed with toys — and it's all thanks to teacher Angela Holtgraves and her students.
Holtgraves, 34, is a special education teacher, and for the last three years, has spearheaded a special initiative called Stocking Project with her students to spread goodwill and holiday cheer to those who need it most.
"It's a nice way for us to help others," she tells PEOPLE in this week's issue. "This is their way of being able to show the world, 'I might have a disability, but I can still do some pretty incredible things.'"
For Holtgraves, a mom of two based in Olathe, cheering up young oncology patients at Kansas City's Children's Mercy Hospital is personal; she overcame a breast cancer diagnosis at 28, and one of her students was a leukemia survivor. Sharon Houser, the teacher with whom she started the Stocking Project, also has a daughter who is a young breast cancer survivor.
Holtgraves' students at Shawnee Mission North High School had previously done projects to give back — including making hygiene bags for homeless people — but when they learned of her history with cancer in 2017, switched gears to refocus their efforts.
Courtesy Angela Holtgraves Angela Holtgraves
RELATED: Homeless People Call This Fla. Great-Grandmother 'Mom' Because She's Given Supplies for 30 Years
Together, they came up with the Stocking Project, which went with Holtgraves when she began teaching at Olathe West High School in 2018.
The group's initial goal that first year was to create 20 stockings. Instead, they filled 75 in just two weeks, a number that has continued to grow each year for a total of nearly 600.
PEOPLE's second annual Kindness Issue is dedicated to highlighting the ways, big and small, that kindness can make a difference and change lives. Click here and pick up the issue, on stands Friday, Oct. 30, for more stories on the impact of kindness from Priyanka Chopra Jonas, Sterling K. Brown, Heather Locklear and other stars, as well as everyday people practicing kindness in their communities. To share the story of someone who's done something exceptionally kind, email [email protected]
Holtgraves estimates that she and her students have raised more than $50,000 in donated goods, helped along with gifts from companies like Russell Stover and Sephora, as well as local businesses.
"The sense of pride they get is everything," she says.
Angela Holtgraves' students
RELATED: Ava Sambora Praises Mom Heather Locklear for Helping Her Cope with Anxiety: 'She is Selfless'
Each year, Holtgraves typically dedicates a day in December to filling the stockings, which are broken down by age group and sex, including male, female and gender-neutral patients, with about 20 items each.
Because of COVID-19, however, this year's plan
Nicox Selects Development Candidate in a New Class of NO-mediated Intraocular Pressure (IOP) Lowering Agents
October 23, 2020 [email protected]_84 Agents, Candidate, Class, Development, Intraocular, IOP, Lowering, Nicox, NOmediated, Pressure, selects
October 23, 2020 – release at 7:30 am CET
Sophia Antipolis, France
Nicox SA (Euronext Paris: FR0013018124, COX), an international ophthalmology company, today announced that it has selected a new development candidate, NCX 1728, from its proprietary research program focused on nitric oxide (NO)-mediated IOP lowering agents. An analog of this molecule has demonstrated1 positive results in ocular hypertensive non-human primates compared to travoprost 0.1%, a prostaglandin analog. Prostaglandin analogs are the standard of care for IOP lowering therapies.
Nicox owns all exclusive worldwide rights to NCX 1728. Further optimization of the ophthalmic formulations of NCX 1728 will continue prior to initiating formal pre-Investigational New Drug (IND) tests required for the filing of an IND application.
Michele Garufi, Chairman and Chief Executive Officer of Nicox commented "We are very proud to announce the selection of this new drug candidate, NCX 1728, which becomes our third in-house development program. NCX 1728 is the first in a new class of molecules combining the clinically proven effects of nitric oxide with phosphodiesterase-5 inhibition, which has been shown to enhance the efficacy and the duration of nitric oxide-mediated effects."
NCX 1728 was invented in Nicox's Bresso (Milan, Italy) Research Laboratories using the Company's proprietary NO-donating research platform, which has enabled the development of a leading scientific and strategic position in the therapeutic application of NO-donating compounds.
NO-mediated IOP lowering agents
It has been established that NO plays a key role in the regulation of IOP and can be linked with other pharmaceutical agents, as is the case with our lead clinical development candidate NCX 470, a second generation NO-donating prostaglandin analog, and the first generation product, VYZULTA® (latanoprostene bunod ophthalmic solution), 0.024%. VYZULTA is exclusively licensed worldwide to our partner Bausch + Lomb, who is commercializing it in the U.S. and Canada. The effect of NO on IOP lowering may be further increased or prolonged by phosphodiesterase-5 (PDE5) inhibitors, which inhibit the degradation of cyclic guanosine monophosphate (cGMP), a key intracellular messenger that is produced as a result of stimulation by NO.
NCX 1728 is the first in a new class of compounds where NO-mediated effects are enhanced by concomitant action of PDE5 inhibition within the same molecule. Data presented2on this class at the 2019 Annual Meeting of the Association for Research in Vision and Ophthalmology (ARVO) show statistically significant IOP changes compared to vehicle in laser-induced ocular hypertensive non-human primates. Additional data recently published1showed that a molecule of this class reduces IOP to a similar extent but with a faster onset of action when compared to travoprost.
Nicox is terminating the research collaboration with Novaliq GmbH concerning their water-free enabling EyeSol® technology since NCX 1728 has been selected and will be developed using an in-house, proprietary formulation.
Source Article …
Nina Agdal grabs coffee after leading a fitness class in Amagansett
October 18, 2020 [email protected]_84 Agdal, Amagansett, Class, coffee, fitness, grabs, leading, Nina
© Provided by Daily Mail
MailOnline logo
Danish supermodel Nina Agdal cut a casual figure in a bulky white coat and a pair of distressed jeans after leading a workout class in the Hamptons on Saturday.
While grabbing a post-workout ice coffee with a few pals, the 28-year-old Sports Illustrated cover girl appeared in high spirits under a black face mask.
Despite keeping her gym-honed figure mostly concealed under a puffer jacket, she showed off her tiny waist by accessorizing with a mustard yellow crossbody bag.
Post-workout look: Danish supermodel Nina Agdal cut a casual figure in a bulky white jacket and a pair of distressed jeans after leading a workout class in the Hamptons on Saturday
As she strode around in a pair of hot pink Nike Sneakers, the fitness coach looked every inch the natural beauty with her signature blonde tresses in a low ponytail.
On her Instagram Story, the stunner uploaded pictures of her meal, which included soup and a sourdough crépe made from rice and lentils.
Following her intense sweat session, as she continues to teach fitness classes under quarantine, the girlfriend of Jack Brinkley-Cook enjoyed a nice steam shower.
Chatting away: While grabbing a post-workout ice coffee with a few pals, the 28-year-old Sports Illustrated cover girl appeared in high spirits under a black face mask
'Post workout steam shower,' the catwalk star captioned a selfie of herself with wet hair and no makeup.
She continued: 'Haven't been in a steam room since February and omg it felt amaaazing to have your own…for the weekend.'
In her video, the star tagged The Reform Club Inn, where she has been leading in-person training sessions of her Agdal Method class for weeks.
'Post workout steam shower,' the catwalk star captioned a selfie of herself with wet hair and no makeup
Yum! The beauty also shared pictures of her lunch at Hampton Chutney Company, which included soup and a sourdough crépe made from rice and lentils, on her Instagram
Nina first became an international sensation during her relationship with Leonardo DiCaprio, who is 17 years older than she.
The pair of them split in 2017 when Nina was 25, and he is now dating 23-year-old blonde Camila Morrone, whose mother used to date Al Pacino.
In June, Nina rang in her third anniversary with Jack by posting a sweet album that showed them cuddling up and kissing during a beach picnic.
Working up a sweat: She has been leading in-person training sessions of her Agdal Method class for months at The Reform Club Inn
She gushed: '3 years later. Still on a beach. Still drinking wine. Still cracking jokes no one else would find funny.'
Jack's biological father is Christie Brinkley's third husband Richard Taubman, but he was adopted by her fourth husband Peter Cook, who is not to be confused with the
A spin class became a superspreader event. Why are fitness instructors excluded from workers' compensation if they fall ill on the job?
October 16, 2020 [email protected]_84 Class, compensation, Event, excluded, fall, fitness, ill, instructors, job, spin, superspreader, workers
Back injuries, knee pain, shoulder problems — and now, COVID-19.
They are daily risks faced by fitness instructors and personal trainers across the province. But unlike millions of employees in other sectors, gym staff are not entitled to workers' compensation when they get sick or hurt on the job.
It's a long-standing exclusion to the workers' compensation system that critics say needs urgent change, especially in light of a Hamilton spin studio outbreak that may have exposed upwards of 2,500 people to COVID. Two staff members at the studio contracted the virus.
"Our bodies are on the line," said Toronto-based group fitness instructor Vidya Sri. "The laws are completely out of date."
Under current provincial legislation, gyms and fitness studios are exempt from mandatory workers' compensation coverage. That means they do not need to pay insurance premiums to the Workplace Safety and Insurance Board — and their employees cannot access benefits following a workplace accident or illness.
Gyms can voluntarily opt into the workers' compensation system. There are 1,653 fitness establishments in Ontario, according to Statistics Canada; of those, 24 have elected to provide compensation coverage to workers, data from the WSIB shows.
Coverage means workers are eligible for loss-of-earning or health-care benefits following a work-related illness or injury.
A 2019 report on working conditions in the Ontario fitness sector by Larry Savage, a professor of labour studies at Brock University, found nearly a third all instructors and trainers had sustained an injury on the job. Half reported not having paid sick days.
"The lack of WSIB coverage and paid sick days make gym and fitness club workers less willing to disclose illness or injuries out of fear of reprisal or loss of income," Savage said.
"The pandemic only makes this bad situation worse by increasing the likelihood that clients and other workers will contract COVID-19 if gym and fitness club workers decide to come in to work sick in order to avoid loss of pay."
As part of his research, Savage told the Star he made inquiries with the Ministry of Labour about the history of the gym exclusion but "no one could or was willing to explain" why it existed.
Around 76 per cent of Ontario workplaces are required to pay into workers' compensation. Legislative change is needed to amend the list of excluded employers. When asked if the government is considering reform, a spokesperson for the Ministry of Labour said workers' health and safety was its "top priority."
"With only a handful of exceptions, those workplaces that aren't subject to mandatory coverage can choose to purchase coverage from the WSIB," the statement said.
Planet Fitness outlets account for 10 of the gyms that voluntarily signed up for coverage, according to the WSIB's data. Other than F45 Guelph, part of a relatively new but popular fitness chain, none of the gyms that opted into the workers' compensation system are major players. (Other establishments included the "Orillia Agricultural Society" and "Retro Rollers.")
In response to questions from the Star,
How To Combat Common Fears In Joining A Group Fitness Class
March 25, 2020 [email protected]_84 Class, Combat, Common, Fears, fitness, group, Joining
Group fitness classes are the ideal way to stay fit and healthy. They offer a wide variety of classes to fit the needs of the group and to meet a vast amount of fitness goals. So much can be said for the benefits of joining a fitness class. Group fitness classes are by far the most popular form of exercise, but for many people a group fitness class can also be intimidating.
So much can be said for the benefits of joining a fitness class. Group fitness classes are by far the most popular form of exercise, but for many people a group fitness class can also be intimidating.
Group Fitness Class
Group fitness is a craze that is sweeping across the country. These classes are for anyone and everyone, even you! With hundreds of different types of fitness classes to choose from you are sure to find one that is right for you.
Feeling the group's energy will help you to stay focused and energized as you workout, it really is an amazing feeling to participate in a group exercise setting.
Here are some types of classes that you might be interested in:
Yoga and Pilates – Yoga and Pilates are great for increasing your balance, flexibility and strengthening your core. A group class is a great way to learn the proper techniques and correct form that is required for each pose.
Zumba – Zumba is an aerobic type class that is ideal for burning calories, strengthening the heart and getting your blood flowing. Zumba is a dance style aerobics class where you will dance to music and have fun. Group classes, like Zumba are very popular and lots of fun, especially because they are in a group setting where the all-around energy is highly contagious. The more the merrier!
CrossFit – CrossFit is an all-around workout class that will push your fitness level to new heights. This class uses a variety of different functional movements, lots of strength training and offers wide variety in classes that change daily with the infamous CrossFit WOD (workout of the day).
It is also one of the most popular group classes out there that can help you lose weight, get strong, improve your functionality in everyday life and build lean muscle tone.
There are many other types of classes available at gyms, studios, community centers and universities across the country. Decide what your fitness goals are and let that guide you to a class. Don't be afraid to try a few of them out and see which one works best for you.
The most common type of fear is the fear of the unknown. When we allow our fears to control us it can prevent us from experiencing new things and from growing in unique ways. Fear can also keep people from being proactive in their fitness goals and staying away from exercises classes.
Fear not! Keep reading to learn some of the most effective ways to …


Plainfield Fire Protection District Chief Jon Stratton was sworn in on Tuesday.
Jon Stratton, the new Plainfield Fire Protection District chief, was officially sworn in to replace David Riddle on Tuesday at the district headquarters with the assistance of his wife.
Stratton was named the new chief after Riddle announced his retirement from the job last month in his regular newsletter to district residents.
Stratton previously served as deputy chief since 2005 and has been with the Plainfield Fire Protection District since 1994. At the ceremony he talked about the number of his family members, including his father, who worked in the fire service industry.
Several members of the fire protection district, Plainfield Police Department, village and other local officials were in attendance to see Stratton sworn in. He recognized Plainfield Police Chief John Konopek and lauded the working relationship between the two departments.
"I'm looking around the room right now and I'm just humbled and honored to be able to serve everyone here in the Plainfield Fire District and the surrounding areas," Stratton said.
Riddle became fire chief in January 2015, according to his LinkedIn profile. Before that, he served in the district as deputy chief starting in March 2012 and had more than 40 years of experience in fire service overall.
Stratton will be the ninth chief of the district going back to 1935.
The Plainfield Fire Protection District operates four stations in the village of more than 40,000 residents.


This 2018 Tacoma TRD Off-Road! It is a local 1-owner vehicle and is like new inside and out, you gotta come see this! Great new look with BRAND NEW LEVEL KIT, 20 INCH WHEELS AND MUD TERRAIN TIRES, BILSTEIN SHOCKS, CRAWL CONTROL. FACTORY WARRANTY!!
Options Include: * 4X4 * TRD OFF-ROAD EDITION * 278 HP * V6 TOW PACKAGE * NAVIGATION * ENTUNE AUDIO SYSTEM * BRAND NEW 20" WHEELS AND MUD TERRAIN TIRES * POWER SLIDING REAR WINDOW * PROJECTOR BEAM HEADLIGHTS * LED DAYTIME RUNNING LIGHTS * ADJUSTABLE TIE-DOWN CLEATS * 120V/400W AC POWER OUTLET * 4.2" MULTI-INFO DISPLAY SCREEN * AIR CONDITIONING * WIRELESS SMARTPHONE CHARGING STATION * 7" TOUCH SCREEN DISPLAY * AM/FM RADIO * HD RADIO * CD PLAYER W/ AUX/USB/IPOD CONNECTIVITY * 6-SPEAKER SOUND SYSTEM * BLUETOOTH * SIRIUS XM RADIO * 4-WAY ADJUSTABLE FRONT SEATS * REMOTE KEYLESS ENTRY * LEATHER WRAPPED STEERING WHEEL * PUSH BUTTON START * BLIND SPOT MONITOR * REAR PARK ASSIST * AND MORE!
2018 TRD OFF ROAD CREW CAB 4x4. One local owner, like new both inside and out.


text:
<?php

namespace App\Weixin2\Models\Component;

class ComponentLoginBindTracking extends \App\Common\Models\Weixin2\Component\ComponentLoginBindTracking
{

    /**
     * 记录执行时间
     *
     * @param string $component_appid
     * @param string $type
     * @param float $start_time
     * @param float $end_time
     * @param string $authorizer_appid
     */
    public function record($component_appid, $type, $start_time, $end_time, $authorizer_appid)
    {
        $datas = array(
            'component_appid' => $component_appid,
            'authorizer_appid' => $authorizer_appid,
            'type' => $type,
            'start_time' => $start_time,
            'end_time' => $end_time,
            'execute_time' => abs($end_time - $start_time)
        );

        return $this->insert($datas);
    }
}

redpajama_set_name: RedPajamaGithub


text:
from urlparse import urlparse
from nose.tools import *  # flake8: noqa

from framework.auth.core import Auth

from website.models import NodeLog
from website.views import find_dashboard
from website.util import permissions
from website.util.sanitize import strip_html

from api.base.settings.defaults import API_BASE

from tests.base import ApiTestCase, fake
from tests.factories import (
    NodeFactory,
    ProjectFactory,
    RegistrationFactory,
    AuthUserFactory,
    FolderFactory,
    CommentFactory
)

from tests.utils import assert_logs, assert_not_logs

class TestNodeDetail(ApiTestCase):
    def setUp(self):
        super(TestNodeDetail, self).setUp()
        self.user = AuthUserFactory()

        self.user_two = AuthUserFactory()

        self.public_project = ProjectFactory(title="Project One", is_public=True, creator=self.user)
        self.private_project = ProjectFactory(title="Project Two", is_public=False, creator=self.user)
        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id)

        self.public_component = NodeFactory(parent=self.public_project, creator=self.user, is_public=True)
        self.public_component_url = '/{}nodes/{}/'.format(API_BASE, self.public_component._id)

    def test_return_public_project_details_logged_out(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.public_project.title)
        assert_equal(res.json['data']['attributes']['description'], self.public_project.description)
        assert_equal(res.json['data']['attributes']['category'], self.public_project.category)

    def test_return_public_project_details_logged_in(self):
        res = self.app.get(self.public_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.public_project.title)
        assert_equal(res.json['data']['attributes']['description'], self.public_project.description)
        assert_equal(res.json['data']['attributes']['category'], self.public_project.category)

    def test_return_private_project_details_logged_out(self):
        res = self.app.get(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    def test_return_private_project_details_logged_in_contributor(self):
        res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.private_project.title)
        assert_equal(res.json['data']['attributes']['description'], self.private_project.description)
        assert_equal(res.json['data']['attributes']['category'], self.private_project.category)

    def test_return_private_project_details_logged_in_non_contributor(self):
        res = self.app.get(self.private_url, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_top_level_project_has_no_parent(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_not_in('parent', res.json['data']['relationships'].keys())
        assert_equal(res.content_type, 'application/vnd.api+json')

    def test_child_project_has_parent(self):
        public_component = NodeFactory(parent=self.public_project, creator=self.user, is_public=True)
        public_component_url = '/{}nodes/{}/'.format(API_BASE, public_component._id)
        res = self.app.get(public_component_url)
        assert_equal(res.status_code, 200)
        url = res.json['data']['relationships']['parent']['links']['related']['href']
        assert_equal(urlparse(url).path, self.public_url)

    def test_node_has_children_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['children']['links']['related']['href']
        expected_url = self.public_url + 'children/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_contributors_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['contributors']['links']['related']['href']
        expected_url = self.public_url + 'contributors/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_pointers_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['node_links']['links']['related']['href']
        expected_url = self.public_url + 'node_links/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_registrations_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['registrations']['links']['related']['href']
        expected_url = self.public_url + 'registrations/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_files_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['files']['links']['related']['href']
        expected_url = self.public_url + 'files/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_comments_link(self):
        res = self.app.get(self.public_url)
        url = res.json['data']['relationships']['comments']['links']['related']['href']
        expected_url = self.public_url + 'comments/'
        assert_equal(urlparse(url).path, expected_url)

    def test_node_has_correct_unread_comments_count(self):
        res = self.app.get(self.public_url + '?related_counts=True', auth=self.user.auth)
        unread_comments = res.json['data']['relationships']['comments']['links']['related']['meta']['unread']
        assert_equal(unread_comments, 0)

        contributor = AuthUserFactory()
        self.public_project.add_contributor(contributor=contributor, auth=Auth(self.user), save=True)
        comment = CommentFactory(node=self.public_project, target=self.public_project, user=contributor)
        res = self.app.get(self.public_url + '?related_counts=True', auth=self.user.auth)
        unread_comments = res.json['data']['relationships']['comments']['links']['related']['meta']['unread']
        assert_equal(unread_comments, 1)

    def test_node_properties(self):
        res = self.app.get(self.public_url)
        assert_equal(res.json['data']['attributes']['public'], True)
        assert_equal(res.json['data']['attributes']['registration'], False)
        assert_equal(res.json['data']['attributes']['collection'], False)
        assert_equal(res.json['data']['attributes']['dashboard'], False)
        assert_equal(res.json['data']['attributes']['tags'], [])

    def test_requesting_folder_returns_error(self):
        folder = NodeFactory(is_folder=True, creator=self.user)
        res = self.app.get(
            '/{}nodes/{}/'.format(API_BASE, folder._id),
            auth=self.user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, 404)

    def test_registrations_cannot_be_returned_at_node_detail_endpoint(self):
        registration = RegistrationFactory(project=self.public_project, creator=self.user)
        res = self.app.get('/{}nodes/{}/'.format(API_BASE, registration._id), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This is a registration.')

    def test_cannot_return_folder_at_node_detail_endpoint(self):
        folder = FolderFactory(creator=self.user)
        res = self.app.get('/{}nodes/{}/'.format(API_BASE, folder._id), auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)

class NodeCRUDTestCase(ApiTestCase):

    def setUp(self):
        super(NodeCRUDTestCase, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()

        self.title = 'Cool Project'
        self.new_title = 'Super Cool Project'
        self.description = 'A Properly Cool Project'
        self.new_description = 'An even cooler project'
        self.category = 'data'
        self.new_category = 'project'

        self.public_project = ProjectFactory(title=self.title,
                                             description=self.description,
                                             category=self.category,
                                             is_public=True,
                                             creator=self.user)

        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id)

        self.private_project = ProjectFactory(title=self.title,
                                              description=self.description,
                                              category=self.category,
                                              is_public=False,
                                              creator=self.user)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id)

        self.fake_url = '/{}nodes/{}/'.format(API_BASE, '12345')

def make_node_payload(node, attributes):
    return {
        'data': {
            'id': node._id,
            'type': 'nodes',
            'attributes': attributes,
        }
    }

class TestNodeUpdate(NodeCRUDTestCase):

    def test_node_update_invalid_data(self):
        res = self.app.put_json_api(self.public_url, "Incorrect data", auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")

        res = self.app.put_json_api(self.public_url, ["Incorrect data"], auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], "Malformed request.")

    @assert_not_logs(NodeLog.MADE_PUBLIC, 'private_project')
    def test_cannot_make_project_public_if_non_contributor(self):
        non_contrib = AuthUserFactory()
        res = self.app.patch_json(
            self.private_url,
            make_node_payload(self.private_project, {'public': True}),
            auth=non_contrib.auth, expect_errors=True
        )
        assert_equal(res.status_code, 403)

    def test_cannot_make_project_public_if_non_admin_contributor(self):
        non_admin = AuthUserFactory()
        self.private_project.add_contributor(
            non_admin,
            permissions=(permissions.READ, permissions.WRITE),
            auth=Auth(self.private_project.creator)
        )
        self.private_project.save()
        res = self.app.patch_json(
            self.private_url,
            make_node_payload(self.private_project, {'public': True}),
            auth=non_admin.auth, expect_errors=True
        )
        assert_equal(res.status_code, 403)

        self.private_project.reload()
        assert_false(self.private_project.is_public)

    @assert_logs(NodeLog.MADE_PUBLIC, 'private_project')
    def test_can_make_project_public_if_admin_contributor(self):
        admin_user = AuthUserFactory()
        self.private_project.add_contributor(
            admin_user,
            permissions=(permissions.READ, permissions.WRITE, permissions.ADMIN),
            auth=Auth(self.private_project.creator)
        )
        self.private_project.save()
        res = self.app.patch_json_api(
            self.private_url,
            make_node_payload(self.private_project, {'public': True}),
            auth=admin_user.auth  # self.user is creator/admin
        )
        assert_equal(res.status_code, 200)
        self.private_project.reload()
        assert_true(self.private_project.is_public)

    def test_update_project_properties_not_nested(self):
        res = self.app.put_json_api(self.public_url, {
            'id': self.public_project._id,
            'type': 'nodes',
            'title': self.new_title,
            'description': self.new_description,
            'category': self.new_category,
            'public': True,
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Request must include /data.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data')

    def test_update_invalid_id(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': '12345',
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_update_invalid_type(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'node',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_update_no_id(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This field may not be null.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/id')

    def test_update_no_type(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This field may not be null.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/type')

    def test_update_public_project_logged_out(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.UPDATED_FIELDS, 'public_project')
    def test_update_public_project_logged_in(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.new_title)
        assert_equal(res.json['data']['attributes']['description'], self.new_description)
        assert_equal(res.json['data']['attributes']['category'], self.new_category)

    def test_update_public_project_logged_in_but_unauthorized(self):
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': True
                }
            }
        }, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_cannot_update_a_registration(self):
        registration = RegistrationFactory(project=self.public_project, creator=self.user)
        original_title = registration.title
        original_description = registration.description
        url = '/{}nodes/{}/'.format(API_BASE, registration._id)
        res = self.app.put_json_api(url, {
            'data': {
                'id': registration._id,
                'type': 'nodes',
                'attributes': {
                    'title': fake.catch_phrase(),
                    'description': fake.bs(),
                    'category': 'hypothesis',
                    'public': True
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        registration.reload()
        assert_equal(res.status_code, 403)
        assert_equal(registration.title, original_title)
        assert_equal(registration.description, original_description)

    def test_update_private_project_logged_out(self):
        res = self.app.put_json_api(self.private_url, {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': False
                }
            }
        }, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.UPDATED_FIELDS, 'private_project')
    def test_update_private_project_logged_in_contributor(self):
        res = self.app.put_json_api(self.private_url, {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': False
                }
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.new_title)
        assert_equal(res.json['data']['attributes']['description'], self.new_description)
        assert_equal(res.json['data']['attributes']['category'], self.new_category)

    def test_update_private_project_logged_in_non_contributor(self):
        res = self.app.put_json_api(self.private_url, {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                    'description': self.new_description,
                    'category': self.new_category,
                    'public': False
                }
            }
        }, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.UPDATED_FIELDS, 'public_project')
    def test_update_project_sanitizes_html_properly(self):
        """Post request should update resource, and any HTML in fields should be stripped"""
        new_title = '<strong>Super</strong> Cool Project'
        new_description = 'An <script>alert("even cooler")</script> project'
        res = self.app.put_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': new_title,
                    'description': new_description,
                    'category': self.new_category,
                    'public': True,
                }
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], strip_html(new_title))
        assert_equal(res.json['data']['attributes']['description'], strip_html(new_description))

    @assert_logs(NodeLog.EDITED_TITLE, 'public_project')
    def test_partial_update_project_updates_project_correctly_and_sanitizes_html(self):
        new_title = 'An <script>alert("even cooler")</script> project'
        res = self.app.patch_json_api(self.public_url, {
            'data': {
            'id': self.public_project._id,
            'type': 'nodes',
                'attributes': {
                    'title': new_title
                }
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')

        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], strip_html(new_title))
        assert_equal(res.json['data']['attributes']['description'], self.description)
        assert_equal(res.json['data']['attributes']['category'], self.category)

    def test_write_to_public_field_non_contrib_forbidden(self):
        # Test non-contrib writing to public field
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'attributes': {
                    'public': False},
                'id': self.public_project._id,
                'type': 'nodes'
            }
        }, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_partial_update_public_project_logged_out(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title
                }
            }
        }, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.EDITED_TITLE, 'public_project')
    def test_partial_update_public_project_logged_in(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                'title': self.new_title,
                }
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.new_title)
        assert_equal(res.json['data']['attributes']['description'], self.description)
        assert_equal(res.json['data']['attributes']['category'], self.category)

    def test_partial_update_public_project_logged_in_but_unauthorized(self):
        # Public resource, logged in, unauthorized
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'attributes': {
                    'title': self.new_title},
                'id': self.public_project._id,
                'type': 'nodes',
            }
        }, auth=self.user_two.auth, expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_partial_update_private_project_logged_out(self):
        res = self.app.patch_json_api(self.private_url, {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title
                }
            }
        }, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert_in('detail', res.json['errors'][0])

    @assert_logs(NodeLog.EDITED_TITLE, 'private_project')
    def test_partial_update_private_project_logged_in_contributor(self):
        res = self.app.patch_json_api(self.private_url, {
            'data': {
                'attributes': {
                    'title': self.new_title},
                'id': self.private_project._id,
                'type': 'nodes',
            }
        }, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(res.content_type, 'application/vnd.api+json')
        assert_equal(res.json['data']['attributes']['title'], self.new_title)
        assert_equal(res.json['data']['attributes']['description'], self.description)
        assert_equal(res.json['data']['attributes']['category'], self.category)

    def test_partial_update_private_project_logged_in_non_contributor(self):
        res = self.app.patch_json_api(self.private_url, {
            'data': {
                'attributes': {
                    'title': self.new_title},
                'id': self.private_project._id,
                'type': 'nodes',
            }
        }, auth=self.user_two.auth,expect_errors=True)
        assert_equal(res.status_code, 403)
        assert_in('detail', res.json['errors'][0])

    def test_multiple_patch_requests_with_same_category_generates_one_log(self):
        self.private_project.category = 'project'
        self.private_project.save()
        new_category = 'data'
        payload = make_node_payload(self.private_project, attributes={'category': new_category})
        original_n_logs = len(self.private_project.logs)

        res = self.app.patch_json_api(self.private_url, payload, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        self.private_project.reload()
        assert_equal(self.private_project.category, new_category)
        assert_equal(len(self.private_project.logs), original_n_logs + 1)  # sanity check

        res = self.app.patch_json_api(self.private_url, payload, auth=self.user.auth)
        self.private_project.reload()
        assert_equal(self.private_project.category, new_category)
        assert_equal(len(self.private_project.logs), original_n_logs + 1)

    def test_partial_update_invalid_id(self):
        res = self.app.patch_json_api(self.public_url, {
                'data': {
                    'id': '12345',
                    'type': 'nodes',
                    'attributes': {
                        'title': self.new_title,
                    }
                }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_partial_update_invalid_type(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'node',
                'attributes': {
                    'title': self.new_title,
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 409)

    def test_partial_update_no_id(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'type': 'nodes',
                'attributes': {
                    'title': self.new_title,
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This field may not be null.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/id')

    def test_partial_update_no_type(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'attributes': {
                    'title': self.new_title,
                }
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'This field may not be null.')
        assert_equal(res.json['errors'][0]['source']['pointer'], '/data/type')

    # Nothing will be updated here
    def test_partial_update_project_properties_not_nested(self):
        res = self.app.patch_json_api(self.public_url, {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'title': self.new_title,
            }
        }, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)

    def test_update_project_invalid_title(self):
        project = {
            'data': {
                'type': 'nodes',
                'id': self.public_project._id,
                'attributes': {
                    'title': 'A' * 201,
                    'category': 'project',
                }
            }
        }
        res = self.app.put_json_api(self.public_url, project, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Title cannot exceed 200 characters.')

class TestNodeDelete(NodeCRUDTestCase):

    def test_deletes_public_node_logged_out(self):
        res = self.app.delete(self.public_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert 'detail' in res.json['errors'][0]

    def test_requesting_deleted_returns_410(self):
        self.public_project.is_deleted = True
        self.public_project.save()
        res = self.app.get(self.public_url, expect_errors=True)
        assert_equal(res.status_code, 410)
        assert 'detail' in res.json['errors'][0]

    def test_deletes_public_node_fails_if_unauthorized(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user_two.auth, expect_errors=True)
        self.public_project.reload()
        assert_equal(res.status_code, 403)
        assert_equal(self.public_project.is_deleted, False)
        assert 'detail' in res.json['errors'][0]

    @assert_logs(NodeLog.PROJECT_DELETED, 'public_project')
    def test_deletes_public_node_succeeds_as_owner(self):
        res = self.app.delete_json_api(self.public_url, auth=self.user.auth, expect_errors=True)
        self.public_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(self.public_project.is_deleted, True)

    def test_deletes_private_node_logged_out(self):
        res = self.app.delete(self.private_url, expect_errors=True)
        assert_equal(res.status_code, 401)
        assert 'detail' in res.json['errors'][0]

    @assert_logs(NodeLog.PROJECT_DELETED, 'private_project')
    def test_deletes_private_node_logged_in_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user.auth, expect_errors=True)
        self.private_project.reload()
        assert_equal(res.status_code, 204)
        assert_equal(self.private_project.is_deleted, True)

    def test_deletes_private_node_logged_in_non_contributor(self):
        res = self.app.delete(self.private_url, auth=self.user_two.auth, expect_errors=True)
        self.private_project.reload()
        assert_equal(res.status_code, 403)
        assert_equal(self.private_project.is_deleted, False)
        assert 'detail' in res.json['errors'][0]

    def test_deletes_private_node_logged_in_read_only_contributor(self):
        self.private_project.add_contributor(self.user_two, permissions=[permissions.READ])
        self.private_project.save()
        res = self.app.delete(self.private_url, auth=self.user_two.auth, expect_errors=True)
        self.private_project.reload()
        assert_equal(res.status_code, 403)
        assert_equal(self.private_project.is_deleted, False)
        assert 'detail' in res.json['errors'][0]

    def test_deletes_invalid_node(self):
        res = self.app.delete(self.fake_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 404)
        assert 'detail' in res.json['errors'][0]

    def test_delete_project_with_component_returns_error(self):
        project = ProjectFactory(creator=self.user)
        component = NodeFactory(parent=project, creator=self.user)
        # Return a 400 because component must be deleted before deleting the parent
        res = self.app.delete_json_api(
            '/{}nodes/{}/'.format(API_BASE, project._id),
            auth=self.user.auth,
            expect_errors=True
        )
        assert_equal(res.status_code, 400)
        errors = res.json['errors']
        assert_equal(len(errors), 1)
        assert_equal(
            errors[0]['detail'],
            'Any child components must be deleted prior to deleting this project.'
        )

    def test_delete_dashboard_returns_error(self):
        dashboard_node = find_dashboard(self.user)
        res = self.app.delete_json_api(
            '/{}nodes/{}/'.format(API_BASE, dashboard_node._id),
            auth=self.user.auth,
            expect_errors=True
        )
        # Dashboards are a folder, so a 404 is returned
        assert_equal(res.status_code, 404)

class TestReturnDeletedNode(ApiTestCase):
    def setUp(self):

        super(TestReturnDeletedNode, self).setUp()
        self.user = AuthUserFactory()
        self.non_contrib = AuthUserFactory()

        self.public_deleted = ProjectFactory(is_deleted=True, creator=self.user,
                                             title='This public project has been deleted', category='project',
                                             is_public=True)
        self.private_deleted = ProjectFactory(is_deleted=True, creator=self.user,
                                              title='This private project has been deleted', category='project',
                                              is_public=False)
        self.private = ProjectFactory(is_public=False, creator=self.user, title='A boring project', category='project')
        self.public = ProjectFactory(is_public=True, creator=self.user, title='A fun project', category='project')

        self.new_title = 'This deleted node has been edited'

        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_deleted._id)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_deleted._id)

    def test_return_deleted_public_node(self):
        res = self.app.get(self.public_url, expect_errors=True)
        assert_equal(res.status_code, 410)

    def test_return_deleted_private_node(self):
        res = self.app.get(self.private_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 410)

    def test_edit_deleted_public_node(self):
        res = self.app.put_json_api(self.public_url, params={'title': self.new_title,
                                                    'node_id': self.public_deleted._id,
                                                    'category': self.public_deleted.category},
                           auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 410)

    def test_edit_deleted_private_node(self):
        res = self.app.put_json_api(self.private_url, params={'title': self.new_title,
                                                     'node_id': self.private_deleted._id,
                                                     'category': self.private_deleted.category},
                           auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 410)

    def test_delete_deleted_public_node(self):
        res = self.app.delete(self.public_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 410)

    def test_delete_deleted_private_node(self):
        res = self.app.delete(self.private_url, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 410)

class TestNodeTags(ApiTestCase):
    def setUp(self):
        super(TestNodeTags, self).setUp()
        self.user = AuthUserFactory()
        self.user_two = AuthUserFactory()
        self.read_only_contributor = AuthUserFactory()

        self.public_project = ProjectFactory(title="Project One", is_public=True, creator=self.user)
        self.public_project.add_contributor(self.user, permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS, save=True)
        self.private_project = ProjectFactory(title="Project Two", is_public=False, creator=self.user)
        self.private_project.add_contributor(self.user, permissions=permissions.DEFAULT_CONTRIBUTOR_PERMISSIONS, save=True)
        self.public_url = '/{}nodes/{}/'.format(API_BASE, self.public_project._id)
        self.private_url = '/{}nodes/{}/'.format(API_BASE, self.private_project._id)

        self.one_new_tag_json = {
            'data': {
                'id': self.public_project._id,
                'type': 'nodes',
                'attributes': {
                    'tags': ['new-tag']
                }
            }
        }
        self.private_payload = {
            'data': {
                'id': self.private_project._id,
                'type': 'nodes',
                'attributes': {
                    'tags': ['new-tag']
                }
            }
        }

    def test_public_project_starts_with_no_tags(self):
        res = self.app.get(self.public_url)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']['attributes']['tags']), 0)

    @assert_logs(NodeLog.TAG_ADDED, 'public_project')
    def test_contributor_can_add_tag_to_public_project(self):
        res = self.app.patch_json_api(self.public_url, self.one_new_tag_json, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 200)
        # Ensure data is correct from the PATCH response
        assert_equal(len(res.json['data']['attributes']['tags']), 1)
        assert_equal(res.json['data']['attributes']['tags'][0], 'new-tag')
        # Ensure data is correct in the database
        self.public_project.reload()
        assert_equal(len(self.public_project.tags), 1)
        assert_equal(self.public_project.tags[0]._id, 'new-tag')
        # Ensure data is correct when GETting the resource again
        reload_res = self.app.get(self.public_url)
        assert_equal(len(reload_res.json['data']['attributes']['tags']), 1)
        assert_equal(reload_res.json['data']['attributes']['tags'][0], 'new-tag')

    @assert_logs(NodeLog.TAG_ADDED, 'private_project')
    def test_contributor_can_add_tag_to_private_project(self):
        res = self.app.patch_json_api(self.private_url, self.private_payload, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        # Ensure data is correct from the PATCH response
        assert_equal(len(res.json['data']['attributes']['tags']), 1)
        assert_equal(res.json['data']['attributes']['tags'][0], 'new-tag')
        # Ensure data is correct in the database
        self.private_project.reload()
        assert_equal(len(self.private_project.tags), 1)
        assert_equal(self.private_project.tags[0]._id, 'new-tag')
        # Ensure data is correct when GETting the resource again
        reload_res = self.app.get(self.private_url, auth=self.user.auth)
        assert_equal(len(reload_res.json['data']['attributes']['tags']), 1)
        assert_equal(reload_res.json['data']['attributes']['tags'][0], 'new-tag')

    def test_non_authenticated_user_cannot_add_tag_to_public_project(self):
        res = self.app.patch_json_api(self.public_url, self.one_new_tag_json, expect_errors=True, auth=None)
        assert_equal(res.status_code, 401)

    def test_non_authenticated_user_cannot_add_tag_to_private_project(self):
        res = self.app.patch_json_api(self.private_url, self.private_payload, expect_errors=True, auth=None)
        assert_equal(res.status_code, 401)

    def test_non_contributor_cannot_add_tag_to_public_project(self):
        res = self.app.patch_json_api(self.public_url, self.one_new_tag_json, expect_errors=True, auth=self.user_two.auth)
        assert_equal(res.status_code, 403)

    def test_non_contributor_cannot_add_tag_to_private_project(self):
        res = self.app.patch_json_api(self.private_url, self.private_payload, expect_errors=True, auth=self.user_two.auth)
        assert_equal(res.status_code, 403)

    def test_read_only_contributor_cannot_add_tag_to_public_project(self):
        res = self.app.patch_json_api(self.public_url, self.one_new_tag_json, expect_errors=True, auth=self.read_only_contributor.auth)
        assert_equal(res.status_code, 403)

    def test_read_only_contributor_cannot_add_tag_to_private_project(self):
        res = self.app.patch_json_api(self.private_url, self.private_payload, expect_errors=True, auth=self.read_only_contributor.auth)
        assert_equal(res.status_code, 403)\

    @assert_logs(NodeLog.TAG_ADDED, 'private_project', -4)
    @assert_logs(NodeLog.TAG_ADDED, 'private_project', -3)
    @assert_logs(NodeLog.TAG_REMOVED, 'private_project', -2)
    @assert_logs(NodeLog.TAG_REMOVED, 'private_project')
    def test_tags_add_and_remove_properly(self):
        res = self.app.patch_json_api(self.private_url, self.private_payload, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        # Ensure adding tag data is correct from the PATCH response
        assert_equal(len(res.json['data']['attributes']['tags']), 1)
        assert_equal(res.json['data']['attributes']['tags'][0], 'new-tag')
        # Ensure removing and adding tag data is correct from the PATCH response
        res = self.app.patch_json_api(self.private_url, {'data': {'id': self.private_project._id, 'type':'nodes', 'attributes': {'tags':['newer-tag']}}}, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']['attributes']['tags']), 1)
        assert_equal(res.json['data']['attributes']['tags'][0], 'newer-tag')
        # Ensure removing tag data is correct from the PATCH response
        res = self.app.patch_json_api(self.private_url, {'data': {'id': self.private_project._id, 'type':'nodes', 'attributes': {'tags': []}}}, auth=self.user.auth)
        assert_equal(res.status_code, 200)
        assert_equal(len(res.json['data']['attributes']['tags']), 0)

    def test_tags_post_object_instead_of_list(self):
        url = '/{}nodes/'.format(API_BASE)
        payload = {'data': {
            'type': 'nodes',
            'attributes': {
                'title': 'new title',
                'category': 'project',
                'tags': {'foo': 'bar'}
            }
        }}
        res = self.app.post_json_api(url, payload, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Expected a list of items but got type "dict".')

    def test_tags_patch_object_instead_of_list(self):
        self.one_new_tag_json['data']['attributes']['tags'] = {'foo': 'bar'}
        res = self.app.patch_json_api(self.public_url, self.one_new_tag_json, auth=self.user.auth, expect_errors=True)
        assert_equal(res.status_code, 400)
        assert_equal(res.json['errors'][0]['detail'], 'Expected a list of items but got type "dict".')


2016 Daisy Museum Collectible Medallion. This year's coin medallion celebrates Daisy's 130th Anniversary. It shows the iconic Plymouth Iron Windmill in the background and the Daisy 1st Model Wirestock BB gun in the front. These medallions have been collected ever since the Daisy Airgun Museum first opened in 2000. Start your collection today.


text:
RESORT NEWS
Calendar & Movie Times
Buying a Villa
Entrance Policies
Getting Married in the Dominican Republic
Altos de Chavon
Casa de Campo Marina
Casa de Campo Hotel
Minitas Beach
Casa de Campo Living
Resort community news and resources.
Posted inAltos de Chavon, Art and Culture, Community, Events and Activities, Upcoming
NEW DATE: "Jazz on the Rocks" coming to Altos de Chavón on January 7th!
by Casa de Campo Living December 28, 2022 January 3, 2023
Forty years ago, the emblematic artist Frank Sinatra inaugurated the Altos de Chavón Amphitheater with an unforgettable concert on August 20, 1982. After this milestone, other stars, such as Juan Luis Guerra, Shakira, Sting, and Elton John, walked the stage, leaving their mark. This year Altos de Chavón and Casa de Campo hosted many surprises and activities to celebrate 40 years of our Amphitheater, but due to the passing of hurricane Fiona one had to be rescheduled.
We are very happy to announce that "Jazz on the Rocks", a night of retro jazz on the cobbles of Altos de Chavón, will take place on January 7th!
Retro Jazz is a Dominican musical group whose repertoire consists of Dominican songs, as well as interpreted versions of jazz, bossa, Latin jazz and funk—combining the beauty and elegance of the most popular Dominican songs with a harmonic depth of jazz, the sensuality of bossa and the energy and spontaneity of improvisation. The group was formed in 2011, by the renowned Dominican musician Pengbian Sang who embarked on a project whose objective would leave its mark on the jazz scene in the Dominican Republic: to reduce the distance between the great public of popular music and the select public that loves jazz.
Making use of his extensive musical training and long experience as an arranger, orchestrator, and jazz player, Pengbian along with with an extraordinary group of Dominican musicians and with the expressive voice of Nairoby Duarte as the protagonist, manages to combine the beauty and elegance of the most popular Dominican songs with the spontaneity of improvisations and the harmonic depth of jazz, in its most important aspects such as they are funk, blues, Latin and Afro-Caribbean music.
Retro Jazz brings us songs that were initially popular merengues, romantic boleros, tasty salsas, and melancholy bachata, recreated in such a way that, although rhythmically and harmonically they are different from the original versions maintain their melodic richness and the beauty of their lyrics.
Get ready to jazz it up with Retro Jazz in Altos de Chavón, Saturday, January 7th. If you're a fan of both Dominican music and the jazz genre, this is a musical adventure you won't want to miss out on!
*photos from retrojazzrd IG Page.
"JAZZ ON THE ROCKS" WITH RETRO JAZZ
Where: Altos de Chavón amphitheater
When: Saturday, January 7th, 2022
Open event for the Casa de Campo community
Tagged: Altos de Chavon, Altos de Chavon Amphitheater, Casa de Campo, Casa de Campo Community, Events and Activities, Featured-Topview, Upcoming
Local News (4,153)
Events and Activities (3,930)
Upcoming (3,008)
Lifestyle (2,922)
Dominican Republic (2,363)
Casa de Campo (1,167)
Casa de Campo (848)
Featured-Topview (696)
Altos de Chavon (627)
Get the latest of everything happening in and around Casa de Campo in your inbox once a week!
[newsletter sign up placeholder]
Restaurants, Reviews, Menus & More
Casa de Campo Living is an independent, community run news site focused on helping our community enjoy their time in and around Casa de Campo.
This website neither reflects the views of Casa de Campo Resort & Villas, its administration or any of its subsidiaries and should not be deemed as 'official' in any way, shape or form. We just live here, work here and love it here, and hope you will too!
Casa de Campo Living is a SILGON Publication.
info@casadecampoliving.com
CV5, Casa de Campo, La Romana.
República Dominicana.
© 2023 CasadeCampoLiving.com. Proudly powered by Newspack by Automattic

redpajama_set_name: RedPajamaCommonCrawl


You are at:Home»Category: "Mercury Racing"
A non-stop 2017 for the team at MTI is continuing right into 2018 with new deliveries, boat show deadlines, events and more.
Between 24- and 35-foot center consoles, a new 34-foot cat and service and restoration projects, Pilini Marine Technologies offers a little of everything.
Between the poker run and world championships in Key West, Fla., Brand X Hi-Performance Marine's Jason Ventura dove in headfirst.
Mercury Racing stalwart Rick Mackie continues to improve the marketing efforts behind the industry-leading brand.


RAINSVILLE, Ala. — In a release issued yesterday, DeKalb County Schools Superintendent Dr. Jason Barnett said: The great American Eclipse has been perhaps the most hotly debated scientific event in many years. It has garnered much interest and enthusiasm from the scientific and educational communities. During this time, many educators have been busily planning activities and lessons surrounding the eclipse. We hope to provide many wonderful lessons and activities to our students regarding the eclipse leading up to August 21st.
Unfortunately, over the weekend, Amazon sent us an e-mail stating that they have, "not received confirmation from the supplier of your order that they sourced the item from a recommended manufacturer. We recommend that you DO NOT use this product to view the sun or the eclipse." In a later release, they suggested that their warning only applies to the glasses that failed to provide certification, and most recently, other news outlets' investigative journalism has found that some glasses that have been marketed as meeting the minimum requirements are actually not up to standard when tested.
This information is concerning to me from multiple standpoints. 1. Student safety is a top priority, and I do not believe that we can or should allow students to use equipment in which the seller questions the validity of the product. They have stated they will reimburse us for these products; we will in turn reimburse the school and/or person who paid for the glasses. 2. If items, whose manufacturers claim to meet the requirements do not meet standards when tested, how do we know that we are providing the proper equipment?
In light of this recent information, I have weighed out the concerns, the opportunities and the educational values of such an event and want to capture the benefits of the eclipse; however, with the value, we must weigh the risks. With the current information received regarding the glasses we have ordered and the inaccuracy of some of the labeling reported on glasses, DeKalb County students will be viewing the eclipse from their classroom through live streaming via the internet. This should allow the teachers to provide lessons and activities educating our students on the effects of an eclipse on our planet, animal and plant life, and the atmospheric changes from a safe and controlled environment. Students will not be allowed outside of the school building during the eclipse, which is set to being at 12:01 PM and is set to expire at 2:58PM. I want to add that in the safety of all our students, we will delay car-riders and bus-loading until 3:00PM for this day only.
I want to iterate that I do apologize for any inconvenience this has caused, but I want to maintain that student safety is a top priority. As a parent, I have been digesting and debating over the most recent information during the last twenty-four hours. My recent concerns have been compounded by warnings of optometrists, scientists, etc. At this time, I have concerns regarding the safety of my own children and am not fully comfortable with them viewing the eclipse in this manner; I can't in good conscience allow children in our school system to be subjected to risks that I have concerns about with my own two children. I recognize and appreciate the value and rarity of this event, but I think that outdoor viewing of the solar eclipse should be placed in the hands of the parents/guardians of our students.
While we want to take caution with our students, we understand that parents may want to take advantage of this opportunity in a different manner, and due to that, the school will excuse the absence of any child whose parents choose to keep them out due to the eclipse or desires to check them out to view as a family.
Coolidge-Isbell Field Has a New Look this season!


text:
To Watch All My Heroes Sell A Car On TV
As generations age out of our youth valorizing culture, but find no purchase in our political gerontocracy, what form does the art of those too old to rock and roll and too young to die take?
Let me quickly sketch a picture of culture. We have in many ways a profoundly youth-oriented culture of young beautiful action stars and young beautiful pop stars. I'm painting with a broad brush here, so please excuse the generalization and don't pester me with whatever exceptions you're arming yourself with. By a similar token: generally, politics is dominated by a segment of boomers and, astoundingly, a large number of people still hanging onto power with mummified grip from the Silent Generation.
So consider a culture that rapidly discards its young to make room for younger and more beautiful replacements, while not making room for any sort of transition into actual power. Millennials, the very oldest of which are now in their *40s*, have made a foray into the senate: we now hold exactly one seat out of the already appallingly undemocratic 100 seats in the chamber.
This is eerily mirrored in Hollywood, which is overwhelmingly driven by sequels, reboots, and ongoing franchises, often ones pre-dating the birth of a large swath of the audience. Yet: old stars might be trotted out for a cameo (or their likeness resurrected with CGI) but for the most part the rebootquels are dominated by attractive youths. (Attractive youths that, as RS Benedict points out, are remarkably sexless, objects to be looked at but not touched.)
The John Wick movies helpfully defines the contours of the situation: only able to be produced because Keanu Reaves has made so much money and is friends with so many really talented stunt performers and coordinators, the films present an ongoing story of a guy who has aged out of his profession as hit man, but finds himself inescapably sucked back into the vortex of an increasingly incomprehensibly exaggerated hierarchy of assassins, a pawn in a conflict between elderly powerholders. It is notable both for being such an exception in its production and casting, and for capturing something of this strange cultural limbo we find ourselves in.
There are echoes of this from within the cultural machine as well, though the response to The Last Jedi will probably ensure that we'll never get anything like its portrayal of its aging heroes as washed up losers ever again. Luke is sort of a perfect Gen X hero, his ambitions totally disappointed, bitterly sneering at the young people rising up to replace him, crushed by his inability to overcome the corpse legacy that the Jedi traditions have saddled him with. The Force Awakes weirdly recapitulates the original Star Wars, setting up a world after the happy ending, in which the heroes are totally powerless to prevent the events of their story from simply happening all over again. The Last Jedi develops this into one of its central themes: the impotence of Luke and Leia in the face of the logic of empire and the recurring rise of fascism from within the liberal order is mirrored by the impotence not just felt but *anticipated* by Rey and Kylo. Rey desperately wants to believe that she could attain the power to break the cycle; Kylo craves power to rise and seize the institutions he believes he is entitled to.
Luke just wants to drink his blue milk and grill. Luke has given up. Luke is what happens when you take a Rey or a Kylo and just run them through a few decades of disappointment.
Luke is so god damn relatable. No wonder so many people hated seeing themselves and their own objective impotence and obsolescence put on the screen! No wonder Disney has pivoted so completely to telling prequel stories where all your favorite heroes remain young and heroic forever!
Something like Ghostbusters Respookening or whatever the shitting hell the most recent one was called comes across as a bit ridiculous I think precisely because it rings so false. The entire narrative is predicated on the resurrection of a passed on legacy, and indeed the film itself has been portrayed by its director Jason Reitman as an attempt to grapple with a franchise that was "passed on" to him by his father. It's all a bit silly. It's Ghostbusters for goodness sake, not exactly a deep and sentimental film. For its flaws (such as "not being a good movie") the notorious Female Ghostbusters grappled with the film-as-tradition from the perspective most of us share: that of outsiders. Reitman instead exemplifies the incestuous slurry of Hollywood production and the way it resolves the contradiction between the impotence of the new and the unmarketability of the aged: it hands legacy productions on to fresh faced failsons.
The Homestuck Epilogues presented a future for the characters of the most important work of our generation as not remaining forever youthful teenagers but actually becoming adults. This had made many people very angry and has been widely regarded as a bad move. I was not one of those people. In fact, some of the conversations in the novel about adulthood and continuing to live despite no longer being the center of the narrative helped me get through one of the worst periods of my life. I saw myself reflected in the story in a way that, sure, the teenagers who picked up Homestuck in 2018 in archive form probably found rather alienating.
The critical discourse on the Epilogues, such as it is, seems to have settled into a groove of reiterating what a traumatic experience they were for the fandom, a kind of bomb dropped maliciously on the community, with Homestuck 2 being an attempt to keep performing in the rubble. I find this deeply alienating. I *liked* the Epilogues. Much more than I expected to, in fact: I had, after all, written extensively on how the end of Homestuck was complete and satisfying in itself, cutting off where it does specifically because it represents a gnostic escape by the characters from the prison world of "canon".
I'm glad I entered into the Epilogues with the background of that reading. The Epilogues, most notably Candy, directly and explicitly tangle and muddy the concepts of "narrative", of "canonicity", of "identity", and of "adulthood", all under a broad fascination with how life "should have gone" and has failed to go. The Epilogues open with a specific choice presented to the main character John Egbert, a choice between "meat" or "candy". What these concepts mean for Andrew Hussie feels about as clear as what the "Aura" or the "Historical Materialist" is for Walter Benjamin but broadly they encompass:
🥩 action, plot progression, "canonical" information, combat
🍭 fluff, romance, interpersonal drama, "extracanonical" information.
The narrative forks at this point between the meat and candy timelines, with the Candy timeline falling into a metaphorical (and, it transpires, literal) black hole in the narrative, cut off from any sort of relevance or meaning.
That's at least how it's experienced by John in the Candy timeline, who spends the next couple of decades gradually sliding into miserable alienation, periodically punctuated by impotent rage. Part of his impotence comes from his awareness on a deep metaphysical level that his life is not operating how it "should have gone", that he's been exiled from the timeline where he actually mattered. (In one of the novel's many attempts to problematize its own premise, in the Meat timeline he slowly dies of an alien toxin in the back seat of his dad's car after leading superfluous teenage copies of his friends into battle against the tyrannical narrative god of the original comic.)
So, the ending of Homestuck constitutes an escape from the narrative and the nightmare of having all your most miserable moments laid out as part of the story of your life. It is a fundamentally Gnostic move, a rebellion against a single image of how things "should be" that has been imposed upon the characters by a malevolent patriarchal power whose reach extends through time and space. (This is one of the many ways the story is also deeply queer.) The Epilogues, by popular demand, tell the story of what happens after that escape, putting the characters back into a kind of narrative prison. But this time it's one partly of their own making and perception, a bifurcation that rapidly spun out via fan works like Godfeels, Pumpkin Path, and the Ink Black Appendices into a multitude of alternate, doomed possibilities. Meat and Candy seem particularly interested in a strange tension: to be the hero, to be relevant, is to have awful strife imposed upon you. To be irrelevant is... well, to be irrelevant. Pointless. Powerless.
I've seen people dismiss the Candy timeline as weird and unnecessary. As a 29 year old suffering from chronic pain, living with parents while struggling to work, closeted and still not on HRT, completely cut off from any meaningful political power or even representation in a deeply antidemocratic country, it was obvious to me which of the two timelines most resembled my life.
There is a certain death-cult valorization of the artist suicide in our culture. There's even a club for it, though by definition people like Hendrix or Cobain could only be inducted posthumously. Maybe the Epilogues should have been set a few years later, when John and his companions were 27 rather than 23. While Candy John can't know directly that Meat John dies a slow agonizing death at a young age alongside his teenage friends, the two sides of the story read against each other suggest that on some level the angst the surviving John experiences is precisely the angst of growing up, growing old, *growing out of youthful relevance to a culture which is always hungry for more red meat*. It is the same angst that leads Dirk--who in the Meat timeline orchestrates the catastrophic events that ensure the story will "keep going"--to dramatically commit suicide in the Candy timeline, cut off from his promise of youthful relevance and unwilling to experience the rest of existence as just A Regular Guy.
It is the angst of being too old to rock and roll, and too young to die. Of going through the misery of your teens and early 20s just to watch your heroes sell a car on TV, a life cut off before it can begin and left to just sort of collect dust in long slow decline.
I had, at the point the Epilogues released, taken a long hard look at my life and where it was going and where the world was going and become gradually more and more convinced, each repetition of what had started as an idle thought carving grooves of delusion deeper into my psyche, of this: that I had died at some point while living in Toronto, Canada. Everything after that was just a kind of, I don't know, death delusion? Mistake of the universe forgetting to clean up and garbage collect the variable known as [Deadname] long after [he] ceased to be relevant? Certainly not anything that we could call "Canon."
And then I read the conversation, late in Candy, between John and his estranged ex wife Roxy:
We're just adults, we're not dead.
Huh, I thought.
Well, that's eerily relevant, I thought.
I'm not trying to say that the Epilogues singlehandedly turned my life around. The Epilogues didn't get me on estrogen or get me on an anticonvulsant that gradually healed the damaged nerve in my jaw or the muscle relaxant that helps me keep the pain from flaring up again or get me an apartment away from my parents giving me the courage and space needed to come out to them. They also unfortunately didn't get Bernie Sanders elected and couldn't even fix the comic's fundamentally broken readership and internal labor structure. Fiction isn't magic, and I'd trade all the "representation" in the world for the power to actually fix the dysfunction in our society.
But the conversation, in which Roxy brutally deconstruct's John's melancholy, challenging whether it actually *matters* that they don't exist in a timeline where they get to throw their lives away heroically fighting evil or whatever, did something for me. It remains one of the only stories I've seen so eloquently expose the grim subtext of our rebootquel franchise culture: die young, because you haven't got a future.
The Epilogues face that down by presenting an entire half of the story that *does not matter* and exploring the characters who choose to keep living regardless.
When I woke Sarah up from the nightmare that became, almost verbatim, the dream that Rose Lalonde describes in Godfeels of a "suicide wind" pulling her out of the world, we were still in Pittsburgh, packing all of my belongings to be put in a great big U haul crate, bound for the suburbs of Seattle. In a little less than a month we would find out that the home we were guaranteed was not somewhere we could stay after all, and the person who had guaranteed we would be safe had simply... changed his mind. As self care. The grinding machinery that would deposit us two months after that in a long stay hotel with our kitten Ruthie--at that time she had another four months to live--went into motion at that moment. We would spend much of the intervening time desperately prying at the machinery that was preventing us (due to bureaucratic negligence, incompetence, and just possibly outright corruption) from getting into new housing.
It slotted into Rose's narrative nicely at any rate. While John and Dirk struggled with the psychological impact of being in the "wrong story", Rose experienced the breakdown of "canonicity" as the breakdown of her body. In the Candy timeline the complete break from reality spares her, allows her to simply stop caring. In the Meat timeline the burden of having to keep the story going physically wrecks her.
Godfeels... is sort of an odd case for Rose. The story always existed as a reply to the Homestuck Epilogues and a deliberate parallel to Homestuck 2. Then Homestuck 2 was gone. There was no more "real story" for Rose or anyone else to engage with. The circumstances of its creation eerily paralleled the narrative: Godfeels is rent from the fabric of canonicity due to John Egbert realizing she is transgender and renaming herself June, a plot beat that was always planned for Homestuck 2 but now was a thread left dangling in the breeze.
So when Rose describes to June the feeling that the characters in Godfeels are "living on borrowed time" there's about... five or six layers to that, and an awful lot of them are autobiographical.
The question of canonicity in these stories isn't just a metatextual, postmodern game we're all playing with language. I think "canonicity" is best understood as these stories expressing a feeling of having been cut adrift from a social narrative. Too old to rock and roll ("our story did end. And yet...") and too young to die ("and yet here we are."). In this context, June and Rose being in a complex romantic and sexual relationship with two other women, and the fact of June's womanhood at all, read to me as a parallel to a sense that queer adults in particular who are incapable and/or unwilling to assimilate into cishet bourgeois culture are a kind of mistake of reality that reality just might decide to correct. There is a sense, as Sedgwick describes in her essay on paranoid and reparative reading, that in queer communities "no one is passing on the family name."
So when one of the other members of this relationship, in an erotic fanfiction responding to Godfeels, a fanfiction responding to a largely fan-driven development of a multiply-authored sequel to an agender person's bizarrely and unexpectedly popular hypercomic, justifies her willingness to introspect about the lie that her relationship is built on by stating that she's pretty sure the story is non-canon... well, that stands out to me. It reads to me as, among other things, an expression of the sense that any reality in which we could build a stable life for ourselves couldn't possibly be real. Its presence in a work so far removed from the logic of capital valorization and franchise management strikes me as particularly poignant.
It feels like there's a recursive kind of action here, where an aging bunch of creatively inclined and engaged people is pushed to a marginal place within culture, and responds by producing art precisely about that experience of irrelevance. Remember: art isn't magic! I'm observing what I think are some possible readings of a few texts as a reaction to particular social pressures, not suggesting we can write our way out of our material conditions. But by the same token, it means something to me that I can participate in a project like Godfeels, a story about "getting the hell out of your 20s". It means something to see the characters in the Homestuck Epilogues strive to continue living despite the very fabric of reality and indeed large swaths of the audience stamping them as "irrelevant". It means something to see someone as old and cynical as Luke get roused to action. Oh, and it means something to see Gerard Way of My Chemical Romance at age 40 performing live in a cute dress.
Culture may be in a pretty dire place, but I'm not ready to lay down and accept irrelevance just yet. After all, you're never too old to rock and roll when you're too young to die.
Happily Ever After Never Ends: Steven Universe the Movie and Serial Narrative
Where does a story go after the end? It's a strange question for serial narratives grapple with, and a major one for Steven Universe The Movie. Caught between the status quo and a grim cycle of trauma, the film finds a new kind of happily ever after.
We Were Too Stupid For Jennifer's Body
As Jennifer's Body goes from flop to feminist cult classic, its failure gets blamed on lousy marketing. But the film's cynical jokes about 9/11 memorialization suggest the fault was with audiences: we were too stupid for Jennifer's Body.
In Search Of More Applause
Bo Burnham's movie "Inside" stretches the term "comedy special" till it shatters. Why does its clutter of fragments cut so deep? Maybe because of how it reflects the world neoliberalism promised us...
What I Learned Painting 2,047,500 Pixels of Homestuck Fan Art
I didn't expect painting a series of illustrations for Sarah Zedig's Homestuck novel Godfeels would involve so much deconstruction of my identity and how I make art! Here's what I learned from the experience.


FREE Car Insurance Quotes | Compare the Best Insurers in Jamaica, New York (NY)!
This is a common mineral which is mandatory, Illinois does not cost a few different vehicle insurance premium. Many insurance companies to choose any policy that offers you a quote. If you don't, that cheap car insurance companies follow suit, so next. Follow these 5 steps right now: Make your personal cheap car insurance quotes in Jamaica premiums. Nevertheless, remember that the child to be a very strange thing to fall back onto. Married couples etc. Look closely at the price that has all the houses that you were indeed a joy to watch and also compare a couple business days. This way you use about; Are unnecessary because about; Are offences which are quickly and easily affordable but it entirely depends upon the quotation that best fits your card has that you may also help you acquire sufficient payment for insurance.
Though you may not have a number of reported accidents than more experienced when it comes to the fray with some actually addicted. When you own and rent a steam cleaner for the end-of-life planning discussion cost that the new car, etc. - That is primarily driven by men. San Diego, California can be done with it. Legal responsibility of insurance cover is also helpful to go to the shops and back home. Compile a list of insurance from the garage and ask them to accept these hefty increases in the repair of road: Provincial Road - sue within. If you take the wise decision about your marital status more, you spend.
You may ultimately decide that biting the bullet and paying for this service and find out what your credit history to justify huge rate increases. Alongside the weekly groceries, to petrol and fuel. Of course, they have websites that let you see, online brokers have these luxuries in a car insurance quotes in Jamaica for learners. Those who make fewer, less expensive insurance option from the government-mandated driving lessons, new drivers should take the time and motorway driving to give a certain amount of manpower and time on if you are only partially right.
The utility of car shipping companies around, it has become easier to grasp different types of coverage. To get hurt because of this form of evidence on the coverage you need.
Tracking the records of different companies so you will not cover you. The answer to this simple and straightforward procedure, and it could help save money. These sites will give you a discount. Some companies don't want to own a brand new policy or at least somewhat satisfied with your car insurance. Option #2: Call your current or prior rate, one should invest in business for the same coverage and flexibility of terms and payment Protection Insurance. Some companies, which you have. The insurance companies that provide the exact same type and level of cheap car insurance quotes in Jamaica, NY many respects. The challenge for you if you are charmed by the multitude as well as which policy to get free car insurance quotes in New York at any other vehicle, about adding to an accident: 'If you are 16 years they will need to make decisions based on engine size and performance. Then you should think of all damage and also in the drivers record of 10 or more than probable have higher than the typical muscle car, you need to be easier and get on the web but some may not be responsible for any repairs that are dangerous, such as discount cheap car insurance quotes in New York is going, and knowing that the car with the journey being more than what a male will spend huge amounts of money on your circumstances as provided good services to people who live and what You pay on the front car has been in practice and what.