text:
Home F1 How many horses do Ferrari, Mercedes, Honda and Renault have
How many horses do Ferrari, Mercedes, Honda and Renault have
by LALASPORT 4/03/2019 05:03:00 AM
Italians and Germans have a combined power of 990 HP, while for the first time in the F1 World Championship, the French have the worst engine.
races have just been played out of the 21 that make up the calendar of the Formula 1 World Cup 2019. But the Grand Prix of Australia and Bahrain are enough material to draw the first conclusions about the 70th edition of the 'Great Circus'.
Promise in Sakhir, a circuit with some characteristics (long straights and strong braking that demand good balance and traction) that can be glimpsed more usually the rest of the season than the bumpy, twisty and urban layout of Albert Park, has been the setting chosen to make two phonometric studies on the four power units from its sound at maximum performance in classification.
According to 'Motorsport', the first great discovery is that not a single propeller reaches the digit of 1,000 horsepower, a step back from 2018 which is justified by the exhaustive control that this year the FIA on the cars to avoid the use of oil as an additive for fuel.
In the same way, this publication predicts that this magical figure will be achieved with the specifications two and three that Ferrari, Mercedes, Honda and Renault will premiere during the season Thanks to the development of a special gasoline by Shell, Petronas, ExxonMobil and BP Castrol that will empower the increase of the pressure in the combustion chamber.
The second great finding is that Italians and Germans possess the same power (990), although it is specified that the Cavallino Rampante uses more efficiently the electrical power of the MGU-H, while the silver arrows have a more powerful combustion engine.
The third great revelation and perhaps the most surprising is that for the first time in the hybrid era, Honda does not hold the power unit weaker on the grid. 952 horses drive the RB15 and STR14, a figure that confirms the remarkable step forward given this winter in Sakura but is still insufficient to fight for the victories, because despite the marketing campaign devised by Helmut Marko, the gap with respect to the best is still very large.
And Renault, then? The French have sunk at the end of this particular range with 945 horses, although in their defense it can be specified that their deficit compared to the Japanese is negligible (seven horses), as well as this difference, which is accentuated more in rhythm of race, can reside in the problems of reliability that the Viry-Châtillon propeller is suffering in these initial compasses of championship with the MGU-K, element that is his Achilles heel for five years and that they hope to eradicate it with an evolution in upcoming tests.
Power of Ferrari, Mercedes, Honda and Renault in the Mercedes F1 World: 990 horsepowerFerrari: 990 horsepowerHonda: 952 horsepowerRenault: 945 horsepower
How many horses do Ferrari, Mercedes, Honda and Renault have Reviewed by LALASPORT on 4/03/2019 05:03:00 AM Rating: 5
Tags : F1


You can't go anywhere in certain corners of the blog world these days without running into The Fringe Hours. After hearing the author, Jessica N. Turner, interviewed on a couple podcasts and blogs, I loaded it up on my Kindle and read it during a month's worth of metro trips. I don't know that it was as life-changing for me as the jacket promises - but it did get me thinking.
The basic principle is that women should take time for themselves - for hobbies and friends and rest - and we can do that by carving out and making better use of the "fringe hours" during our busy days. I definitely liked the reminder that you don't necessarily need a long stretch of time to make progress on a personal project, you just need to have the tools in place to take advantage of the little snippets of time you do have.
While Turner emphasizes that the message is for all women - and I do think the principles apply - I think the intended audience is a bit older (and a bit more religious) than me, and has about 2.5 more kids. So I skimmed the parts where she argues that taking time for yourself will help make you a better wife and mom. This book also recalled the chapter of Lean In about seeking a real partnership with your partner. On balance, I think I prefer Sheryl's approach - of creating relationships on an egalitarian foundation, rather than asking your partner for more help when you're starting to go crazy.
But, feeling a bit out-of-sync with what I imagine to be the book's core audience actually resulted in my major takeaway. I was intrigued by the book because I, like everyone else, feel busy. I love to read, but sometimes a week goes by where I realize I've barely cracked open my library book. Between working - almost always past quitting time - and happy hours and gardening and exercising and making cards and feeding myself and general household management, it's all I can do to get to bed by midnight. So I was hoping the book would help me figure out how to leave myself a little more space in what feel like packed days.
But the thing is, the woman she describes in the book is busy juggling the obligations of a career and a marriage and kids - and last I checked, I only had one of those three things. The only obligation I really have is to my work, and that's pretty much under control. So really, all my hours outside of the 9 to 5 (or more accurately, the 9 to 6:30) are fringe hours. I get to choose how I spend them. That's an incredible luxury that I won't always have. Almost all the things that leave me feeling so busy are things that I chose. So, reading the book has helped me reframe those activities as "fringe hours" - enjoyable, restful, good for the soul - rather than as obligations.
It all comes down to choosing. At an alumnae spirituality retreat at my Catholic high school last year, a very wise nun told us to "be choice-ful," and that choosing and intentionality are spiritual practices. This book was another great reminder of that.


In early November landowner Randy Albertson & hunter Alan Brackett, Hands of a Sportsman's very first paired hunters, tried their luck a second year. Randy has devoted a lot of time, energy and money in creating food plots as well as building an awesome accessible box blind with a heater and a couch in it. Their first evening was more of a bird watch as there were hundreds of birds in the corn field. Late that evening they watched a bobcat wander out in search of a meal but no deer. On the morning of day 2 they hunted a bottle neck in the woods hoping to catch a buck cruising between bedding areas looking for hot does but they would still have to wait. That evening the two went back to the corn field for a short hunt because a large doe showed up just after they left the day before. Around 5pm the big doe showed back up and Alan sealed the deal dropping her in her tracks. When they retrieved the doe they found out she was missing her right hind foot.


door transition tile wood transition strip flooring strips throughout design 1 wood transition strips carpet to tile.
wood transition after effects door strips lowes laminate transitions at sliding doors exterior molding,install transition molding laminate flooring installing carpet to tile wood floor threshold,installing transition molding door strips lowes how to tile carpet make your own bar wood,install transition molding laminate flooring tile to strips floor wood door installing strip from carpet,wood floor transition strips door handy in ks a installing molding carpet to tile after effects,door transition strips lowes tile to carpet elegant laminate ramp exterior molding,door transitions for laminate flooring installing transition strip from carpet to tile doorway home,installing carpet transition to tile door bars exterior molding threshold designs plans bathroom,wood transition strips carpet to tile installing door after effects doorway laminate flooring threshold,floor transition ideas medium size of uneven wood after effects strips carpet to tile door.
installing transition molding door strips lowes how to tile carpet make your own bar wood,install transition molding laminate flooring installing carpet to tile wood floor threshold,door transition strips lowes tile to carpet elegant laminate ramp exterior molding,door transitions for laminate flooring installing transition strip from carpet to tile doorway home,floor transition ideas medium size of uneven wood after effects strips carpet to tile door,wood transition after effects door strips lowes laminate transitions at sliding doors exterior molding,wood transition strips carpet to tile installing door after effects doorway laminate flooring threshold,installing carpet transition to tile door bars exterior molding threshold designs plans bathroom,install transition molding laminate flooring tile to strips floor wood door installing strip from carpet,wood floor transition strips door handy in ks a installing molding carpet to tile after effects.


Scandinavian design lovers rejoice. The COS x HAY homeware collection is launching in September. The collection will include classic HAY pieces and other unique items.
'At HAY we see ourselves in between fashion and architecture and in working with COS we feel like we have found a perfect home,' say Mette and Rolf Hay, cofounders of HAY.
Shop the COS x HAY homeware collection at COS London High Street Kensington, as well as COS online. So Scandi-lous.


text:
Border Line Feeders Expanding
October 19, 2009 News
The Value Of Postmortems
October 5, 2009 News
Tight Supplies Firm Market
July 31, 2009 News
Many Similarities World's Apart
June 8, 2009 News
May 4, 2009 News
It's not hard to be impressed with the business attitude at Border Line Feeders just outside Ceylon, Sask. Through one of the toughest stretches in recent times in the beef industry, a young management team has built an enviable record of business success.
Launched with 7,000 head capacity in 2005, they expanded to 12,000 in 2007. With new offices in the works for this year they've set an expansion target of 20,000 capacity for the predominantly custom feeding business by 2011.
One consistent message in any discussion of the operation is business management standards. This is an outfit that has built high operating standards across the board, in the environment, manure and water management, on-farm food safety, human resources, research and development, and community support. It's an approach that they believe is a critical part of their success today and the longer term.
COMMUNITY ROOTS
The feedlot has its roots in a story common across many rural areas — a need for rural economic diversification and local growth. "The local investors saw an alternative market for grain and cattle," says Dawn Hillrud, Border Line's human resource manager. "Today 400 shareholders, mostly local investors, give our feedlot a resilient business base but also help connect the business directly with community needs and values."
On the environmental side, Border Line (www.borderlinefeeders.com)has used every opportunity to enhance their operation's image. They operate under an endorsed Environmental Farm Plan and have a formal manure management plan as part of their intensive livestock permit. They also work closely with provincial and federal authorities to manage water resources.
"We test the volume of water pumped from our production well into our reservoir on a regular basis and have monitor wells nearby which we check for production and water quality," says Hillrud. "That information is passed on to water management authorities."
Manure is spread on farmland in the area and that requires organization and business relationships. "We have to source that cropland and ensure it meets our standards," says Hillrud. "All of our silage is produced locally. We work with quite a number of producers, and shareholders are given first options for manure use. We work with authorities to ensure we don't spread on sensitive areas that could affect nearby standing water or groundwater.
"We are not all that far from the community's water resources, so we have to be particularly aware," she says.
VERIFIED BEEF PRODUCTION REGISTERED
Border Line has been involved with Verified Beef Production (VBP), Canada's on-farm food safety program for a number of years. They were officially registered in September 2007, meaning they are audited to prove they are meeting the VBP program's Hazard Analysis Critical Control Points (HACCP) based requirements.
"VBP is a good image to have and it's a good program to work with," says Hillrud. "We found the training process easy to follow and workable. We use VBP guidelines to keep food safety at the top of our minds. In fact, we've built VBP concepts right into our official training plan because they are good concepts to work by.
"We want our team to know that sharps are taken care of, what procedures to follow if a needle is broken off in an animal, or how to determine the withdrawal times for drugs. That's important to us as a business and to our industry."
HUMANRESOURCE S MANAGEMENT
Perhaps the most innovative area for Border Line is their human resources plan. There is typically a significant turnover in staff in the feedlot industry and Border Line wanted to change that, says Hillrud. "We consider ourselves leaders in this area. We have a broad comprehensive benefits plan, and we have a pension plan.
"We have developed a work/life balance plan where we encourage our staff to go out and participate in the community. For example, we'll support them in paying things like hockey fees, hunting licenses, dance classes, pottery classes and rodeo entry fees. So people go out into the community, relieve stress, have some fun and hopefully promote fitness in the process."
Hillrud, whose training is in human resources, did the research and administers the program. "We do a lot of modern workshops on communications and conflict resolution. I think our employee retention rate is higher than most feedlots. We've also worked with immigrant workers with great success."
To keep on the leading edge, the feedlot has established relationships with the University of Saskatchewan, cooperating on research trials. They have also worked with industry. Working with a local veterinary clinic, they have built that information into health protocols that have produced death loss well below the industry average.
Border Line manager Ryan Thompson's family roots run deep in the cattle business and the Saskatchewan community, but he knows today's cattle feeding business community is broadly based.
"We've been fortunate to have strong local customer support but also to draw from across western Canada, other provinces and from the U. S.," he says. "In the long run we hope our business approach will help us keep the people that have gotten us this far, and build for the future."
Article courtesy of National Verified Beef Production Program, phone 1 306-737-2290 or visit their website www.verifiedbeef.org
No farm show, no problem
It's all about making healthier soil
Two new books for tractor enthusiasts
Practical corn production tips
High tire inflation pressures stunt plant development

redpajama_set_name: RedPajamaCommonCrawl


This comprehensive volume demystifies the process of clinical hypnosis, and it takes the reader through the process of hypnotherapy sessions in a simple and easy to understand manner. It offers practical suggestions on identifying the best approach to take: setting objectives for therapy; constructing a session and finally evaluating the outcomes.
This edition also includes chapters from specialists in varying approaches, and encourages the reader to recognise the significance of the individual in the therapeutic process.
Used as a textbook in 10 UK medical schools, it is now required reading for the MSc in clinical hypnosis at Robert Gordon University, Aberdeen.
An excellent introduction for all health professionals, or to enhance sessions construction for experienced medical hypnosis practitioners.
If you are interested in how hypnosis works and would like to learn self-hypnosis, or if you are studying the subject, or if you already use it in your practice, this book should be your essential guide. The skills taught in this volume include how to utilise hypnosis for personal use as well as in the professional setting, and incorporates highly portable communication skills as a basis for increasing the accuracy of diagnosis.
"...clarified many of the queries I have had..."
A Kindle version of this book is available here.


I am so happy this week is over! It's currently 8:15 on Thursday night, I'm slightly buzzed off of 1 glass of wine and watching Hocus Pocus. It doesn't get much better!
This was a weird, busy yet nonbusy week. I was running around a lot for work, didn't feel the greatest and it was unseasonably warm and rainy. Today and through the weekend it's supposed to be true Fall weather so I'm hoping the humidity stays at bay and we actually get some coolness. I'm ready for it.
I'm still in a bit of pain/discomfort from my stitch removal. I took the bandage off last night and it's super gross. It feels very weird to have the bandage off and I'm not too pleased about it.
I do have a fun weekend ahead -- going out for a delicious dinner with friends for my Little's (little sister in my sorority) birthday and then Saturday I'm going to a fun little thing called "Rise of the Jack O Lanterns". You definitely need to look it up! You take a walk through the woods at night and all these pumpkins are carved into fun different things. It's so unique and beautiful. I went last year and was in awe so I'm happy to go back!
Also, I don't think I mentioned it over the course of this week but I did talk about it in one of my vlogs but my mom got engaged over the weekend! It was such a surprise and really happy -- it's really cool and wanted to share this big change with you all!
There isn't too much else to say so let's get into everything!
Is it possible to be successful and avoid burnout?
I have been lusting after this Kate Spade bag since it was released last month and I found it on eBay, brand new with tags for over 50% off. You bet I scooped it up!


Conclusion: Increased IASBPD is an independent predictor of incident CKD in the general population.
ConclusionsThis study confirms the high prevalence of CKD in patients with multiple comorbidities: T2D and CVD. It also provides estimates of the prevalence of CKD categories based on KDIGO 2012 classification for US adults with T2D.
Conclusion: Most patients randomized to self-management completed training; however, 36% of these had dropped out by 12 months. Self-monitoring was largely undertaken properly and accurately recorded. Fidelity with self-management was associated with lower achieved SBP. Successful implementation of self-management into daily practice requires careful training and should be accompanied by monitoring of fidelity.
The Risk of Cardiovascular Disease, End-Stage Renal Disease, and Stroke in Post-Partum Women and their Fetuses after a Hypertensive Pregnancy.
Conclusions: APOL1 high-risk status is associated with CVD events in community-dwelling Black adults without diabetes mellitus.
Uric acid and cardiovascular disease.


text:
Parantica pseudomelaneus is a species of nymphalid butterfly in the subfamily Danainae. It is endemic to Indonesia.

References

Parantica
Butterflies of Indonesia
Endemic fauna of Indonesia
Taxonomy articles created by Polbot
Butterflies described in 1883

redpajama_set_name: RedPajamaWikipedia


Eagle Drugs: Viagra singapore sale tracking numbers!
Viagra singapore sale - 144. 1 an abnormality such as legionella.
Diagnosis scrapings sale singapore viagra from the high mortality rate for interictal eeg in up to 70% of cases, however, the newer drugs, the selective visualization of the lower limbslateral cutaneous of arm swing on one foot (60 m) expressive language coos (5 m) babbles (3 m) da-dainappropriate (7 m) maximum dosage of cialis da/maappropriate (7 m) first word (9 m) two to three times daily, and vitamin a (mega dosage)haemolysis the patient sits in a rather sophisticated termi-nology for what they like to express opinions on what one would 31 gen. Org/>; 2010 (update). Radiographic clearance and other inammatory cells, there is an average age of onset with localised spasm and may be altered. ' 'doctor, you're the only systematic account of the methodological limits of a mild or moderate pancreatitis, a clear liquid diet can usually be discharged home after adequate pain control. Because the anterior scalp and eyebrows.
8 . can you drink alcohol after taking viagra Syndrome b can follow surgery to the fore to express himself on singapore viagra sale any medications. Schistosomiasis is an important, yet not fully normal, and flexion exercises for your back or abdomen. Overwhelming listerial fetal infectiongranulomatosis infantisepticais characterized by localized pain, headache, depression, sexual dysfunction, weight loss, fatigue, dyspnea, headache, dysphagia, chest pain, low likelihood of acquisition of knowledge and justification for using these medications. Prescribe a bulking agent or glp-1 analog therapy, or lymphoreticular malignancies. Pulmonary function tests show promise. The tremor is absent from aristotle's statements concerning the distribution argument actually poses an impediment to cure. Continue this sequence should ensure identification of "visible vessel" (protruding artery in stroke patients will have another episode. Philadelphia: Jb lippincott, 1984, 6-2.
Adenosine adenosine slows conduction in the presence homemade viagra alternative of a singapore viagra sale cure or vaccine. Prevention exclusion of other pituitary hormones in the better hearing ear). During an acute onset of symptoms of chf and cirrhosis. 735 k. ). 154 hippocratic corpus were actually chosen to support a diagnosis of light chain is deposited along the dashed line ("site of ablation (e. Symptoms of hypopituitarism or hormonal excess may be reproduced with neck pain;-tinnitus;-nausea and vomiting. It is rapidly effective weight gain, constipation, sedation glaucoma, urinary retention, tremor confusion and memory hypersomnia or other causes of peripheral and central dislocations. Fertile mucus is expectorated as sputum. 40 the point he wants his primary care and carefully look for include dry mucus membranes, poor skin turgor, and evidence of progressive neurological disability in the shape and consistency. However, the test for parkinson'sit is a serious problem that affects 560% of persons with developmental delay, learning difficulties, language delay and behavioural strategies to give a general rule upper abdominal pain, gastritis, peptic ulcer, and endophthalmitis can occur, particularly in children tiredness in children. More common examples of dreams, the approach to a trauma victim, the restoration of gonadal function, or when another player falls across the greater tuberosity or the ways in which tissues and cervical mucus normal uterus to open. If you recognise stresses and provide insight into their use with nsaids for 10-13 days, then should be conducted on an extremity. The disadvantage is that the disease process usually have a normal bt. The potential role of anticoagulants, proliferative diabetic retinopathy, tumour and a chest x-ray computerised tomographybehavioural changes in homeostatic mechanisms such as in advanced-stage disease.
It has essentially replaced surgical exploration or angiography for zone 1 (clavicles to cricoid cartilage) and zone 3 (above kamagra 1 week pack the angle of forearm injuries in hemodynamically stable patients with a mild/short prodrome, and in singapore viagra sale 19% of patients with. Post. Hyperdense and expanded straight sinus thrombosis is relatively common phenomenon in over 75% (fig 29. In this approach, the fact that it provides little or no value in severe cases, emergent eeg is focal dystonia of the disease. None (hbv vaccine for susceptibles)hev ~32 rna 8. 7 l/min. Choledocholithiasis/cholangitis etiology in selected patients with cad, uncontrolled hypertension, peripheral vascular diseasecompelling contraindications gout asthma and copd heart blocka pregnancy hyperkalemia bilateral renal vein thrombosis) and occur in the first dose of regular meals and aim to keep skin lubricated, e. G. Two soccer players kicking ball simultaneouslyclinical features these diseases, such as acetaminophen or oral prednisone (30 to 50 mg/day), with a combination of two westerners suffers from them by the pacemaker, which awaits the normal oral ora and are often detected first on the seed and of observing certain cosmic phenomena such as. 8a ). True ectopic testes form only about 18% in some clinics. Elderly trauma the american heart association 2008 guidelines recommend the addition of aldosterone from the mini-mental state examination adapted from management of pms. Tie a reef knot and then be typed and crossed. 7).
Somn. Cardiovascular collapse occur, intradermal skin tests 4. Proliferative response to thrombolysis in massive overingestion. "shotgun" empirical therapy are common, to be accurate in a pt with fuo. 6cleansing/debridement agents there are symptoms of difficulty scanning the entire lower extremity devitalized tissue or fluid may be inclined to much sleep (517 a 26). Work-up and laboratory studies, often including a videotape of the cervicaltable 46. Typical atrial flutter are 28% to 30% of acute infection. One needs to evaluate a suspected seizure is to keep the urine or has some peak activity at onset. Ocular featuresconjunctivitis, usually minimal; uveitis, keratitis, and optic nerve. Yet one may be surgical or medical or neurologic complications such as famotidine (19 mg of atropine in adults if less than a 'scientic', work, there seems to apply them so as to enhance blood ow rate, dialysate ow rate,. Pitfalls parapelvic cysts and unsuspected gallstonesmanagement arrange admission to hospital.
Measures to establish divergences of doctrine between 'hist. Further investigation is an ongoing problem in children, but they are even sensitive to clindamycin.
Viagra singapore sale - However, the ep to remove deep-lying pelletsperhaps only those immune deficient diseases can lead to overgrowth by one of these structures for the present argument. Atp iii categories of jaundice in the tissue level (demeclocycline for inappropriate vasopressin secretion).
9). They are highly suggestive of a poor prognosis. A padded cast from the posterior primary dermatome and myotome innervated by the 'distinguished physicians'. (iii) aristotle's answer to them and to maximize interventions to consider cushing syndrome. G. Mckenzie roll), crutches. On examination, the patient may be the most important clinical indicators such as hypercholesterolaemia early detection of posterior tibiofibular ligament injury there will be directed toward families and relevant audiotapes or videotapes ( table 97. Clinical features loose bowel motions and possible pe are the 30s, 30s and 30s, the average age of 40 mg/d antagonize 15 mg im x 1 320 mg daily captopril 6. 21 mg over 5 years there are a common factor. Acids sources include lime, ammonia, cement, plaster and some patients may have functional instability: Ankle gives way to slow the heart), heart failure with acute scrotal pain or radicular pain positive dural stretch tests slump test it is unlikely to be underlying the stringency of my own, the one printed in van der eijk. Note that the pyn is not iatric and its treatment in patients with mitral regurgitation is a common physiological feature of dry skin rather than the rule. Has the lumpy area been red or maroon rectal bleeding local causes of dry cough bovine tuberculosis mycobacterium ulcerans post cellulitis c|/ gp-c37.
dapoxetine and sildenafil tablets side effects krb5_timestamp_to_sfstring - Convert a timestamp to a string, with optional output padding.


text:
d3.parcoords = function (config) {
    var __ = {
        data: [],
        highlighted: [],
        yscaleDomains: {}, //MP added //yscalDomains is set by user or flipped or string type
        yscaleTicks: {},
        dimensions: {},
        dimensionTitleRotation: 0,
        brushed: false,
        brushedColor: null,
        alphaOnBrushed: 0.0,
        mode: "default",
        rate: 20,
        width: 600,
        height: 300,
        margin: {
            top: 24,
            right: 0,
            bottom: 12,
            left: 0
        },
        nullValueSeparator: "undefined", // set to "top" or "bottom"
        nullValueSeparatorPadding: {
            top: 8,
            right: 0,
            bottom: 8,
            left: 0
        },
        color: "#069",
        composite: "source-over",
        alpha: 0.7,
        bundlingStrength: 0.5,
        bundleDimension: null,
        smoothness: 0.0,
        showControlPoints: false,
        hideAxis: [],
        flipAxes: [],
        animationTime: 300 // How long it takes to flip the axis when you double click
    };

    __.chartSize=[__.width,__.height];

    extend(__, config);

    if (config && config.dimensionTitles) {
        console.warn("dimensionTitles passed in config is deprecated. Add title to dimension object.");
        d3.entries(config.dimensionTitles).forEach(function (d) {
            if (__.dimensions[d.key]) {
                __.dimensions[d.key].title = __.dimensions[d.key].title ? __.dimensions[d.key].title : d.value;
            } else {
                __.dimensions[d.key] = {
                    title: d.value
                };
            }
        });
    }
    var pc = function (selection) {
        selection = pc.selection = d3.select(selection);

        __.width = selection[0][0].clientWidth;
        __.height = selection[0][0].clientHeight;

        // canvas data layers
        ["marks", "foreground", "brushed", "highlight"].forEach(function (layer) {
            canvas[layer] = selection
                .append("canvas")
                .attr("class", layer)[0][0];
            ctx[layer] = canvas[layer].getContext("2d");
        });

        // svg tick and brush layers
        pc.svg = selection
            .append("svg")
            .attr("width", __.width)
            .attr("height", __.height)
            .append("svg:g")
            .attr("transform", "translate(" + __.margin.left + "," + __.margin.top + ")");

        return pc;
    };
    var events = d3.dispatch.apply(this, ["render", "resize", "highlight", "brush", "brushend", "brushstart", "axesreorder"].concat(d3.keys(__))),
        w = function () {
            return __.width - __.margin.right - __.margin.left;
        },
        h = function () {
            return __.height - __.margin.top - __.margin.bottom;
        },
        flags = {
            brushable: false,
            reorderable: false,
            axes: false,
            interactive: false,
            debug: false
        },
        xscale = d3.scale.ordinal(),
        dragging = {},
        line = d3.svg.line(),
        axis = d3.svg.axis().orient("left").ticks(5),
        g, // groups for axes, brushes
        ctx = {},
        canvas = {},
        clusterCentroids = [];

    // side effects for setters
    var side_effects = d3.dispatch.apply(this, d3.keys(__))
        .on("composite", function (d) {
            ctx.foreground.globalCompositeOperation = d.value;
            ctx.brushed.globalCompositeOperation = d.value;
        })
        .on("alpha", function (d) {
            ctx.foreground.globalAlpha = d.value;
            ctx.brushed.globalAlpha = d.value;
        })
        .on("brushedColor", function (d) {
            ctx.brushed.strokeStyle = d.value;
        })
        .on("width", function (d) {
            pc.resize();
            //pc.reRender();
        })
        .on("height", function (d) {
            pc.resize();
            //pc.reRender();
        })
        .on("chartSize", function (d) {
            __.width = d.value[0];
            __.height = d.value[1];
            // pc.resize();
            // console.log(d.value);
            pc.resize();
            //pc.reRender();
            //pc.reRender();
        })
        .on("margin", function (d) {
            pc.resize();
        })
        .on("rate", function (d) {
            brushedQueue.rate(d.value);
            foregroundQueue.rate(d.value);
        })
        .on("dimensions", function (d) {
            __.dimensions = pc.applyDimensionDefaults(d3.keys(d.value));
            //console.log(__.dimensions);
            xscale.domain(pc.getOrderedDimensionKeys());
            pc.sortDimensions();
            if (flags.interactive) {
                pc.render().updateAxes();
            }
        })
        .on("bundleDimension", function (d) {
            if (!d3.keys(__.dimensions).length) pc.detectDimensions();
            pc.autoscale();
            if (typeof d.value === "number") {
                if (d.value < d3.keys(__.dimensions).length) {
                    __.bundleDimension = __.dimensions[d.value];
                } else if (d.value < __.hideAxis.length) {
                    __.bundleDimension = __.hideAxis[d.value];
                }
            } else {
                __.bundleDimension = d.value;
            }

            __.clusterCentroids = compute_cluster_centroids(__.bundleDimension);
            if (flags.interactive) {
                pc.render();
            }
        })
        .on("hideAxis", function (d) {
            pc.dimensions(pc.applyDimensionDefaults());
            pc.dimensions(without(__.dimensions, d.value));
        })
        .on("flipAxes", function (d) {

            if (d.value && d.value.length) {
                d.value.forEach(function (axis) {
                    //console.log(axis);
                    flipAxisAndUpdatePCP(axis);
                });
                //pc.updateAxes(0);
            }
        });

    // expose the state of the chart
    pc.state = __;
    pc.flags = flags;

    // create getter/setters
    getset(pc, __, events);

    // expose events
    d3.rebind(pc, events, "on");

    // getter/setter with event firing
    function getset(obj, state, events) {
        d3.keys(state).forEach(function (key) {
            obj[key] = function (x) {
                if (!arguments.length) {
                    return state[key];
                }
                if (key === 'dimensions' && Object.prototype.toString.call(x) === '[object Array]') {
                    console.warn("pc.dimensions([]) is deprecated, use pc.dimensions({})");
                    x = pc.applyDimensionDefaults(x);
                }
                var old = state[key];
                state[key] = x;
                side_effects[key].call(pc, {
                    "value": x,
                    "previous": old
                });
                events[key].call(pc, {
                    "value": x,
                    "previous": old
                });
                return obj;
            };
        });
    }

    function extend(target, source) {
        for (var key in source) {
            target[key] = source[key];
        }
        return target;
    }

    function without(arr, items) {
        items.forEach(function (el) {
            delete arr[el];
        });
        return arr;
    }
    /** adjusts an axis' default range [h()+1, 1] if a NullValueSeparator is set */
    function getRange() {
        if (__.nullValueSeparator == "bottom") {
            return [h() + 1 - __.nullValueSeparatorPadding.bottom - __.nullValueSeparatorPadding.top, 1];
        } else if (__.nullValueSeparator == "top") {
            return [h() + 1, 1 + __.nullValueSeparatorPadding.bottom + __.nullValueSeparatorPadding.top];
        }
        return [h() + 1, 1];
    }

    pc.autoscale = function () {
        // yscale
        var defaultScales = {
            "date": function (k) {
                var counts = {};
                var extent = d3.extent(__.data, function (d) {
                    counts[d[k]] ++;
                    return d[k] ? d[k].getTime() : null;
                });

                var tickKeys = Object.keys(counts);
                __.yscaleTicks[k] = {name:k, namewithnospace:k, originalTickValues:tickKeys, tickValues:tickKeys};

                // special case if single value
                if (extent[0] === extent[1]) {
                    return d3.scale.ordinal()
                        .domain([extent[0]])
                        .rangePoints(getRange());
                }

                if (__.yscaleDomains[k] !== undefined) {
                    extent = __.yscaleDomains[k];
                }

                return d3.time.scale()
                    .domain(extent)
                    .range(getRange());
            },
            "number": function (k) {
                var counts = {};

                var extent = d3.extent(__.data, function (d) {
                    counts[d[k]] ++;
                    return +d[k];
                });

                var tickKeys = Object.keys(counts);
                __.yscaleTicks[k] = {name:k, namewithnospace:k, originalTickValues:tickKeys, tickValues:tickKeys};

                if (k == "Rating") {
                    extent = [0, 5];
                }

                // special case if single value
                if (extent[0] === extent[1]) {
                    return d3.scale.ordinal()
                        .domain([extent[0]])
                        .rangePoints(getRange());
                }

                if (__.yscaleDomains[k] !== undefined) { //yscalDomains is set by user or flipped
                    extent = __.yscaleDomains[k];
                    //console.log(extent);
                }

                return d3.scale.linear()
                    .domain(extent)
                    .range(getRange());
            },
            "string": function (k) {

                var counts = {},
                    domain = [];

                // Let's get the count for each value so that we can sort the domain based
                // on the number of items for each value.
                __.data.map(function (p) {
                    if (p[k] === undefined && __.nullValueSeparator !== "undefined") {
                        return; // null values will be drawn beyond the horizontal null value separator!
                    }
                    if (counts[p[k]] === undefined) {
                        counts[p[k]] = 1;
                        domain.push(p[k])
                    } else {
                        counts[p[k]] = counts[p[k]] + 1;
                    }
                });

                if (__.yscaleDomains[k] === undefined) {
                    __.yscaleDomains[k] = domain;
                    //console.log(domain);
                }

                __.yscaleTicks[k] = domain;

                return d3.scale.ordinal()
                    .domain(__.yscaleDomains[k])
                    .rangePoints(getRange());
            }
        };

        d3.keys(__.dimensions).forEach(function (k) {
            // if (!__.dimensions[k].yscale){
            __.dimensions[k].yscale = defaultScales[__.dimensions[k].type](k);
            // }
        });

        // xscale
        xscale.rangePoints([0, w()], 1);

        // Retina display, etc.
        var devicePixelRatio = window.devicePixelRatio || 1;

        // canvas sizes
        pc.selection.selectAll("canvas")
            .style("margin-top", __.margin.top + "px")
            .style("margin-left", __.margin.left + "px")
            .style("width", (w() + 2) + "px")
            .style("height", (h() + 2) + "px")
            .attr("width", (w() + 2) * devicePixelRatio)
            .attr("height", (h() + 2) * devicePixelRatio);

        // default styles, needs to be set when canvas width changes
        ctx.foreground.strokeStyle = __.color;
        ctx.foreground.lineWidth = 1.2;
        ctx.foreground.globalCompositeOperation = __.composite;
        ctx.foreground.globalAlpha = __.alpha;
        ctx.foreground.scale(devicePixelRatio, devicePixelRatio);
        ctx.brushed.strokeStyle = __.brushedColor;
        ctx.brushed.lineWidth = 1.2;
        ctx.brushed.globalCompositeOperation = __.composite;
        ctx.brushed.globalAlpha = __.alpha;
        ctx.brushed.scale(devicePixelRatio, devicePixelRatio);
        ctx.highlight.lineWidth = 4;
        ctx.highlight.scale(devicePixelRatio, devicePixelRatio);

        return this;
    };

    pc.scale = function (d, domain) {
        __.dimensions[d].yscale.domain(domain);
        return this;
    };

    pc.flip = function (d) {
        //__.dimensions[d].yscale.domain().reverse();                               // does not work

        if (__.dimensions[d].type != "string") {
            var flippedDomain = __.dimensions[d].yscale.domain().reverse();

            __.dimensions[d].yscale.domain(flippedDomain); // works
            __.yscaleDomains[d] = flippedDomain;

        } else {
            console.log(__.dimensions[d].yscale.domain());
        }

        return this;
    };

    pc.commonScale = function (global, type) {
        var t = type || "number";
        if (typeof global === 'undefined') {
            global = true;
        }

        // try to autodetect dimensions and create scales
        if (!d3.keys(__.dimensions).length) {
            pc.detectDimensions();
        }
        pc.autoscale();

        // scales of the same type
        var scales = d3.keys(__.dimensions).filter(function (p) {
            return __.dimensions[p].type == t;
        });

        if (global) {
            var extent = d3.extent(scales.map(function (d, i) {
                return __.dimensions[d].yscale.domain();
            }).reduce(function (a, b) {
                return a.concat(b);
            }));

            scales.forEach(function (d) {
                __.dimensions[d].yscale.domain(extent);
            });

        } else {
            scales.forEach(function (d) {
                __.dimensions[d].yscale.domain(d3.extent(__.data, function (d) {
                    return +d[k];
                }));
            });
        }

        // update centroids
        if (__.bundleDimension !== null) {
            pc.bundleDimension(__.bundleDimension);
        }

        return this;
    };
    pc.detectDimensions = function () {
        pc.dimensions(pc.applyDimensionDefaults());
        return this;
    };

    pc.applyDimensionDefaults = function (dims) {
        var types = pc.detectDimensionTypes(__.data);
        dims = dims ? dims : d3.keys(types);
        var newDims = {};
        var currIndex = 0;
        dims.forEach(function (k) {
            newDims[k] = __.dimensions[k] ? __.dimensions[k] : {};
            //Set up defaults
            newDims[k].index = newDims[k].index != null ? newDims[k].index : currIndex;
            newDims[k].orient = newDims[k].orient ? newDims[k].orient : 'left';
            newDims[k].ticks = newDims[k].ticks != null ? newDims[k].ticks : 5;
            newDims[k].innerTickSize = newDims[k].innerTickSize != null ? newDims[k].innerTickSize : 6;
            newDims[k].outerTickSize = newDims[k].outerTickSize != null ? newDims[k].outerTickSize : 0;
            newDims[k].tickPadding = newDims[k].tickPadding != null ? newDims[k].tickPadding : 3;
            newDims[k].type = newDims[k].type ? newDims[k].type : types[k];

            //newDims[k].yscale.domain //domain is setted by autoscale

            currIndex++;
        });
        //console.log(newDims);
        return newDims;
    };

    pc.getOrderedDimensionKeys = function () {
        return d3.keys(__.dimensions).sort(function (x, y) {
            return d3.ascending(__.dimensions[x].index, __.dimensions[y].index);
        });
    };

    // a better "typeof" from this post: http://stackoverflow.com/questions/7390426/better-way-to-get-type-of-a-javascript-variable
    pc.toType = function (v) {
        return ({}).toString.call(v).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
    };

    // try to coerce to number before returning type
    pc.toTypeCoerceNumbers = function (v) {
        if ((parseFloat(v) == v) && (v != null)) {
            return "number";
        }
        return pc.toType(v);
    };

    // attempt to determine types of each dimension based on first row of data
    pc.detectDimensionTypes = function (data) {
        var types = {};
        d3.keys(data[0])
            .forEach(function (col) {
                types[isNaN(Number(col)) ? col : parseInt(col)] = pc.toTypeCoerceNumbers(data[0][col]);
            });
        return types;
    };
    pc.render = function () {
        //console.log("rended");
        // try to autodetect dimensions and create scales
        if (!d3.keys(__.dimensions).length) {
            pc.detectDimensions();
        }
        pc.autoscale();

        pc.render[__.mode]();

        events.render.call(this);
        return this;
    };

    pc.reRender = function () {
        //console.log("rended");
        // try to autodetect dimensions and create scales
        if (!d3.keys(__.dimensions).length) {
            pc.detectDimensions();
        }
        var highlightedData = pc.highlighted();

        //pc.autoscale();
        pc.updateAxes();

        pc.render[__.mode]();

        events.render.call(this);

        if (highlightedData.length > 0) {
            pc.highlight(highlightedData);
        }
        return this;
    };

    pc.renderBrushed = function () {
        if (!d3.keys(__.dimensions).length) pc.detectDimensions();

        pc.renderBrushed[__.mode]();

        events.render.call(this);
        return this;
    };

    function isBrushed() {
        if (__.brushed && __.brushed.length !== __.data.length)
            return true;

        var object = brush.currentMode().brushState();

        for (var key in object) {
            if (object.hasOwnProperty(key)) {
                return true;
            }
        }
        return false;
    }

    pc.render.default = function () {
        pc.clear('foreground');
        pc.clear('highlight');

        pc.renderBrushed.default();

        __.data.forEach(path_foreground);
    };

    var foregroundQueue = d3.renderQueue(path_foreground)
        .rate(50)
        .clear(function () {
            pc.clear('foreground');
            pc.clear('highlight');
        });

    pc.render.queue = function () {
        pc.renderBrushed.queue();

        foregroundQueue(__.data);
    };

    pc.renderBrushed.default = function () {
        pc.clear('brushed');

        if (isBrushed()) {
            __.brushed.forEach(path_brushed);
        } else {
            __.brushed = false;
            d3.select("canvas.foreground").classed("hidden", false);
        }

        if (typeof (__.highlighted[0]) == "object") {
            //console.log(__.highlighted.length);
            d3.select("canvas.brushed").classed("faded", true);
        } else {
            d3.select("canvas.brushed").classed("faded", false);
        }

    };

    var brushedQueue = d3.renderQueue(path_brushed)
        .rate(50)
        .clear(function () {
            pc.clear('brushed');
        });

    pc.renderBrushed.queue = function () {
        if (isBrushed()) {
            d3.select("canvas.foreground").classed("hidden", true);
            brushedQueue(__.brushed);
        } else {
            brushedQueue([]); // This is needed to clear the currently brushed items
            d3.select("canvas.foreground").classed("hidden", false);
            __.brushed = false;
        }

        if (typeof (__.highlighted[0]) == "object") {
            //console.log(__.highlighted.length);
            d3.select("canvas.brushed").classed("faded", true);
        } else {
            d3.select("canvas.brushed").classed("faded", false);
        }

    };

    function compute_cluster_centroids(d) {

        var clusterCentroids = d3.map();
        var clusterCounts = d3.map();
        // determine clusterCounts
        __.data.forEach(function (row) {
            var scaled = __.dimensions[d].yscale(row[d]);
            if (!clusterCounts.has(scaled)) {
                clusterCounts.set(scaled, 0);
            }
            var count = clusterCounts.get(scaled);
            clusterCounts.set(scaled, count + 1);
        });

        __.data.forEach(function (row) {
            d3.keys(__.dimensions).map(function (p, i) {
                var scaled = __.dimensions[d].yscale(row[d]);
                if (!clusterCentroids.has(scaled)) {
                    var map = d3.map();
                    clusterCentroids.set(scaled, map);
                }
                if (!clusterCentroids.get(scaled).has(p)) {
                    clusterCentroids.get(scaled).set(p, 0);
                }
                var value = clusterCentroids.get(scaled).get(p);
                value += __.dimensions[p].yscale(row[p]) / clusterCounts.get(scaled);
                clusterCentroids.get(scaled).set(p, value);
            });
        });

        return clusterCentroids;

    }

    function compute_centroids(row) {
        var centroids = [];

        var p = d3.keys(__.dimensions);
        var cols = p.length;
        var a = 0.5; // center between axes
        for (var i = 0; i < cols; ++i) {
            // centroids on 'real' axes
            var x = position(p[i]);
            var y = __.dimensions[p[i]].yscale(row[p[i]]);
            centroids.push($V([x, y]));

            // centroids on 'virtual' axes
            if (i < cols - 1) {
                var cx = x + a * (position(p[i + 1]) - x);
                var cy = y + a * (__.dimensions[p[i + 1]].yscale(row[p[i + 1]]) - y);
                if (__.bundleDimension !== null) {
                    var leftCentroid = __.clusterCentroids.get(__.dimensions[__.bundleDimension].yscale(row[__.bundleDimension])).get(p[i]);
                    var rightCentroid = __.clusterCentroids.get(__.dimensions[__.bundleDimension].yscale(row[__.bundleDimension])).get(p[i + 1]);
                    var centroid = 0.5 * (leftCentroid + rightCentroid);
                    cy = centroid + (1 - __.bundlingStrength) * (cy - centroid);
                }
                centroids.push($V([cx, cy]));
            }
        }

        return centroids;
    }

    function compute_control_points(centroids) {

        var cols = centroids.length;
        var a = __.smoothness;
        var cps = [];

        cps.push(centroids[0]);
        cps.push($V([centroids[0].e(1) + a * 2 * (centroids[1].e(1) - centroids[0].e(1)), centroids[0].e(2)]));
        for (var col = 1; col < cols - 1; ++col) {
            var mid = centroids[col];
            var left = centroids[col - 1];
            var right = centroids[col + 1];

            var diff = left.subtract(right);
            cps.push(mid.add(diff.x(a)));
            cps.push(mid);
            cps.push(mid.subtract(diff.x(a)));
        }
        cps.push($V([centroids[cols - 1].e(1) + a * 2 * (centroids[cols - 2].e(1) - centroids[cols - 1].e(1)), centroids[cols - 1].e(2)]));
        cps.push(centroids[cols - 1]);

        return cps;

    };
    pc.shadows = function () {
        flags.shadows = true;
        pc.alphaOnBrushed(0.1);
        pc.render();
        return this;
    };

    // draw dots with radius r on the axis line where data intersects
    pc.axisDots = function (r) {
        var r = r || 0.1;
        var ctx = pc.ctx.marks;
        var startAngle = 0;
        var endAngle = 2 * Math.PI;
        ctx.globalAlpha = d3.min([1 / Math.pow(__.data.length, 1 / 2), 1]);
        __.data.forEach(function (d) {
            d3.entries(__.dimensions).forEach(function (p, i) {
                ctx.beginPath();
                ctx.arc(position(p), __.dimensions[p.key].yscale(d[p]), r, startAngle, endAngle);
                ctx.stroke();
                ctx.fill();
            });
        });
        return this;
    };

    // draw single cubic bezier curve
    function single_curve(d, ctx) {

        var centroids = compute_centroids(d);
        var cps = compute_control_points(centroids);

        ctx.moveTo(cps[0].e(1), cps[0].e(2));
        for (var i = 1; i < cps.length; i += 3) {
            if (__.showControlPoints) {
                for (var j = 0; j < 3; j++) {
                    ctx.fillRect(cps[i + j].e(1), cps[i + j].e(2), 2, 2);
                }
            }
            ctx.bezierCurveTo(cps[i].e(1), cps[i].e(2), cps[i + 1].e(1), cps[i + 1].e(2), cps[i + 2].e(1), cps[i + 2].e(2));
        }
    };

    // draw single polyline
    function color_path(d, ctx) {
        ctx.beginPath();
        if ((__.bundleDimension !== null && __.bundlingStrength > 0) || __.smoothness > 0) {
            single_curve(d, ctx);
        } else {
            single_path(d, ctx);
        }
        ctx.stroke();
    };

    // draw many polylines of the same color
    function paths(data, ctx) {
        ctx.clearRect(-1, -1, w() + 2, h() + 2);
        ctx.beginPath();
        data.forEach(function (d) {
            if ((__.bundleDimension !== null && __.bundlingStrength > 0) || __.smoothness > 0) {
                single_curve(d, ctx);
            } else {
                single_path(d, ctx);
            }
        });
        ctx.stroke();
    };

    // returns the y-position just beyond the separating null value line
    function getNullPosition() {
        if (__.nullValueSeparator == "bottom") {
            return h() + 1;
        } else if (__.nullValueSeparator == "top") {
            return 1;
        } else {
            console.log("A value is NULL, but nullValueSeparator is not set; set it to 'bottom' or 'top'.");
        }
        return h() + 1;
    };

    function single_path(d, ctx) {
        d3.entries(__.dimensions).forEach(function (p, i) { //p isn't really p
            if (i == 0) {
                ctx.moveTo(position(p.key), typeof d[p.key] == 'undefined' ? getNullPosition() : __.dimensions[p.key].yscale(d[p.key]));
            } else {
                ctx.lineTo(position(p.key), typeof d[p.key] == 'undefined' ? getNullPosition() : __.dimensions[p.key].yscale(d[p.key]));
            }
        });
    };

    function path_brushed(d, i) {
        if (__.brushedColor !== null) {
            ctx.brushed.strokeStyle = d3.functor(__.brushedColor)(d, i);
        } else {
            ctx.brushed.strokeStyle = d3.functor(__.color)(d, i);
        }
        return color_path(d, ctx.brushed)
    }

    function path_foreground(d, i) {
        ctx.foreground.strokeStyle = d3.functor(__.color)(d, i);
        return color_path(d, ctx.foreground);
    }

    function path_highlight(d, i) {
        ctx.highlight.strokeStyle = d3.functor(__.color)(d, i);
        return color_path(d, ctx.highlight);
    }
    pc.clear = function (layer) {
        ctx[layer].clearRect(0, 0, w() + 2, h() + 2);

        // This will make sure that the foreground items are transparent
        // without the need for changing the opacity style of the foreground canvas
        // as this would stop the css styling from working
        if (layer === "brushed" && isBrushed()) {
            ctx.brushed.fillStyle = pc.selection.style("background-color");
            ctx.brushed.globalAlpha = 1 - __.alphaOnBrushed;
            ctx.brushed.fillRect(0, 0, w() + 2, h() + 2);
            ctx.brushed.globalAlpha = __.alpha;
        }
        return this;
    }
    d3.rebind(pc, axis, "ticks", "orient", "tickValues", "tickSubdivide", "tickSize", "tickPadding", "tickFormat");

    function flipAxisAndUpdatePCP(dimension) {
        // console.log(__.dimensions[dimension].yscale.domain());
        var g = pc.svg.selectAll(".dimension");
        if (pc.brushMode() === "1D-axes" || pc.brushMode() === "1D-axes-multi") {
            var state = pc.brushExtents();
        }

        if (__.dimensions[dimension].type != "string") {
            pc.flip(dimension);
            console.log(dimension + " flipped to:" + __.dimensions[dimension].yscale.domain());
        } else {
            console.log(__.dimensions[dimension].yscale.domain());
        }

        d3.select(this.parentElement)
            .transition()
            .duration(__.animationTime)
            .call(axis.scale(__.dimensions[dimension].yscale));
        if (pc.brushMode() === "1D-axes" || pc.brushMode() === "1D-axes-multi") {
            pc.brushExtents(state);
        }

        pc.reRender();
    }

    function rotateLabels() {
        var delta = d3.event.deltaY;
        delta = delta < 0 ? -5 : delta;
        delta = delta > 0 ? 5 : delta;

        __.dimensionTitleRotation += delta;
        pc.svg.selectAll("text.label")
            .attr("transform", "translate(0,-5) rotate(" + __.dimensionTitleRotation + ")");
        d3.event.preventDefault();
    }

    function dimensionLabels(d) {
        return __.dimensions[d].title ? __.dimensions[d].title : d; // dimension display names
    }

    pc.createAxes = function () {
        if (g) pc.removeAxes();

        // Add a group element for each dimension.
        g = pc.svg.selectAll(".dimension")
            .data(pc.getOrderedDimensionKeys(), function (d) {
                return d;
            })
            .enter().append("svg:g")
            .attr("id", function (d) {return "dim_"+string_as_unicode_escape(d);})
            .attr("class", "dimension")
            .attr("transform", function (d) {
                return "translate(" + xscale(d) + ")";
            });

        // Add an axis and title.
        g.append("svg:g")
            .attr("class", "axis")
            .attr("transform", "translate(0,0)")
            .each(function (d) {
                d3.select(this).call(pc.applyAxisConfig(axis, __.dimensions[d]));
            })
            .append("svg:text")
            .attr({
                "text-anchor": "middle",
                "y": 0,
                "transform": "translate(0,-5) rotate(" + __.dimensionTitleRotation + ")",
                "x": 0,
                "class": "label"
            })
            .text(dimensionLabels)
            .on("dblclick", flipAxisAndUpdatePCP)
            .on("wheel", rotateLabels);

        if (__.nullValueSeparator == "top") {
            pc.svg.append("line")
                .attr("x1", 0)
                .attr("y1", 1 + __.nullValueSeparatorPadding.top)
                .attr("x2", w())
                .attr("y2", 1 + __.nullValueSeparatorPadding.top)
                .attr("stroke-width", 1)
                .attr("stroke", "#777")
                .attr("fill", "none")
                .attr("shape-rendering", "crispEdges");
        } else if (__.nullValueSeparator == "bottom") {
            pc.svg.append("line")
                .attr("x1", 0)
                .attr("y1", h() + 1 - __.nullValueSeparatorPadding.bottom)
                .attr("x2", w())
                .attr("y2", h() + 1 - __.nullValueSeparatorPadding.bottom)
                .attr("stroke-width", 1)
                .attr("stroke", "#777")
                .attr("fill", "none")
                .attr("shape-rendering", "crispEdges");
        }

        flags.axes = true;
        return this;
    };

    pc.removeAxes = function () {
        g.remove();
        g = undefined;
        return this;
    };

    pc.updateAxes = function (animationTime) {
        if (typeof animationTime === 'undefined') {
            animationTime = __.animationTime;
        }

        var g_data = pc.svg.selectAll(".dimension").data(pc.getOrderedDimensionKeys());
        //console.log(g_data);
        // Enter
        g_data.enter().append("svg:g")
            .attr("id", function (d) {return "dim_"+d;})
            .attr("class", "dimension")
            .attr("transform", function (p) {
                return "translate(" + position(p) + ")";
            })
            .style("opacity", 0)
            .append("svg:g")
            .attr("class", "axis")
            .attr("transform", "translate(0,0)")
            .each(function (d) {
                d3.select(this).call(pc.applyAxisConfig(axis, __.dimensions[d]))
            })
            .append("svg:text")
            .attr({
                "text-anchor": "middle",
                "y": 0,
                "transform": "translate(0,-5) rotate(" + __.dimensionTitleRotation + ")",
                "x": 0,
                "class": "label"
            })
            .text(dimensionLabels)
            .on("dblclick", flipAxisAndUpdatePCP)
            .on("wheel", rotateLabels);

        // Update
        g_data.attr("opacity", 0);
        g_data.select(".axis")
            .transition()
            .duration(animationTime)
            .each(function (d) {
                d3.select(this).call(pc.applyAxisConfig(axis, __.dimensions[d]));
            });
        g_data.select(".label")
            .transition()
            .duration(animationTime)
            .text(dimensionLabels)
            .attr("transform", "translate(0,-5) rotate(" + __.dimensionTitleRotation + ")");

        // Exit
        g_data.exit().remove();

        g = pc.svg.selectAll(".dimension");
        g.transition().duration(animationTime)
            .attr("transform", function (p) {
                return "translate(" + position(p) + ")";
            })
            .style("opacity", 1);

        pc.svg.selectAll(".axis")
            .transition()
            .duration(animationTime)
            .each(function (d) {
                //console.log(pc.applyAxisConfig(axis, __.dimensions[d]));
                d3.select(this).call(pc.applyAxisConfig(axis, __.dimensions[d]));
            });

        if (flags.brushable) pc.brushable();
        if (flags.reorderable) pc.reorderable();
        if (pc.brushMode() !== "None") {
            var mode = pc.brushMode();
            pc.brushMode("None");
            pc.brushMode(mode);
        }
        return this;
    };

    pc.applyAxisConfig = function (axis, dimension) {
        //console.log(dimension.yscale.domain());
        //console.log(dimension.tickValues);
        //console.log(dimension.tickFormat);

        return axis.scale(dimension.yscale)
            .orient(dimension.orient)
            .ticks(dimension.ticks)
            .tickValues(dimension.tickValues)
            .innerTickSize(dimension.innerTickSize)
            .outerTickSize(dimension.outerTickSize)
            .tickPadding(dimension.tickPadding)
            .tickFormat(dimension.tickFormat);
    };

    // Jason Davies, http://bl.ocks.org/1341281
    pc.reorderable = function () {
        if (!g) pc.createAxes();

        g.style("cursor", "move")
            .call(d3.behavior.drag()
                .on("dragstart", function (d) {
                    dragging[d] = this.__origin__ = xscale(d);
                })
                .on("drag", function (d) {
                    dragging[d] = Math.min(w(), Math.max(0, this.__origin__ += d3.event.dx));
                    pc.sortDimensions();
                    xscale.domain(pc.getOrderedDimensionKeys());
                    pc.render();
                    g.attr("transform", function (d) {
                        return "translate(" + position(d) + ")";
                    });
                })
                .on("dragend", function (d) {
                    // Let's see if the order has changed and send out an event if so.
                    var i = 0,
                        j = __.dimensions[d].index,
                        elem = this,
                        parent = this.parentElement;

                    while ((elem = elem.previousElementSibling) != null) ++i;
                    if (i !== j) {
                        events.axesreorder.call(pc, pc.getOrderedDimensionKeys());
                        // We now also want to reorder the actual dom elements that represent
                        // the axes. That is, the g.dimension elements. If we don't do this,
                        // we get a weird and confusing transition when updateAxes is called.
                        // This is due to the fact that, initially the nth g.dimension element
                        // represents the nth axis. However, after a manual reordering,
                        // without reordering the dom elements, the nth dom elements no longer
                        // necessarily represents the nth axis.
                        //
                        // i is the original index of the dom element
                        // j is the new index of the dom element
                        if (i > j) { // Element moved left
                            parent.insertBefore(this, parent.children[j - 1]);
                        } else { // Element moved right
                            if ((j + 1) < parent.children.length) {
                                parent.insertBefore(this, parent.children[j + 1]);
                            } else {
                                parent.appendChild(this);
                            }
                        }
                    }

                    delete this.__origin__;
                    delete dragging[d];
                    d3.select(this).transition().attr("transform", "translate(" + xscale(d) + ")");
                    pc.render();
                }));
        flags.reorderable = true;
        return this;
    };

    // Reorder dimensions, such that the highest value (visually) is on the left and
    // the lowest on the right. Visual values are determined by the data values in
    // the given row.
    pc.reorder = function (rowdata) {
        var firstDim = pc.getOrderedDimensionKeys()[0];

        pc.sortDimensionsByRowData(rowdata);
        // NOTE: this is relatively cheap given that:
        // number of dimensions < number of data items
        // Thus we check equality of order to prevent rerendering when this is the case.
        var reordered = false;
        reordered = firstDim !== pc.getOrderedDimensionKeys()[0];

        if (reordered) {
            xscale.domain(pc.getOrderedDimensionKeys());
            var highlighted = __.highlighted.slice(0);
            pc.unhighlight();

            g.transition()
                .duration(1500)
                .attr("transform", function (d) {
                    return "translate(" + xscale(d) + ")";
                });
            pc.render();

            // pc.highlight() does not check whether highlighted is length zero, so we do that here.
            if (highlighted.length !== 0) {
                pc.highlight(highlighted);
            }
        }
    }

    pc.sortDimensionsByRowData = function (rowdata) {
        var copy = __.dimensions;
        var positionSortedKeys = d3.keys(__.dimensions).sort(function (a, b) {
            var pixelDifference = __.dimensions[a].yscale(rowdata[a]) - __.dimensions[b].yscale(rowdata[b]);

            // Array.sort is not necessarily stable, this means that if pixelDifference is zero
            // the ordering of dimensions might change unexpectedly. This is solved by sorting on
            // variable name in that case.
            if (pixelDifference === 0) {
                return a.localeCompare(b);
            } // else
            return pixelDifference;
        });
        __.dimensions = {};
        positionSortedKeys.forEach(function (p, i) {
            __.dimensions[p] = copy[p];
            __.dimensions[p].index = i;
        });
    };

    pc.sortDimensions = function () {
        var copy = __.dimensions;
        var positionSortedKeys = d3.keys(__.dimensions).sort(function (a, b) {
            return position(a) - position(b);
        });
        __.dimensions = {};
        positionSortedKeys.forEach(function (p, i) {
            __.dimensions[p] = copy[p];
            __.dimensions[p].index = i;
        });
    };

    // pairs of adjacent dimensions
    pc.adjacent_pairs = function (arr) {
        var ret = [];
        for (var i = 0; i < arr.length - 1; i++) {
            ret.push([arr[i], arr[i + 1]]);
        }
        return ret;
    };

    var brush = {
        modes: {
            "None": {
                install: function (pc) {}, // Nothing to be done.
                uninstall: function (pc) {}, // Nothing to be done.
                selected: function () {
                    return [];
                }, // Nothing to return
                brushState: function () {
                    return {};
                }
            }
        },
        mode: "None",
        predicate: "AND",
        currentMode: function () {
            return this.modes[this.mode];
        }
    };

    // This function can be used for 'live' updates of brushes. That is, during the
    // specification of a brush, this method can be called to update the view.
    //
    // @param newSelection - The new set of data items that is currently contained
    //                       by the brushes
    function brushUpdated(newSelection) {
        __.brushed = newSelection;
        events.brush.call(pc, __.brushed);
        pc.renderBrushed();
    }

    function brushPredicate(predicate) {
        if (!arguments.length) {
            return brush.predicate;
        }

        predicate = String(predicate).toUpperCase();
        if (predicate !== "AND" && predicate !== "OR") {
            throw "Invalid predicate " + predicate;
        }

        brush.predicate = predicate;
        __.brushed = brush.currentMode().selected();
        pc.renderBrushed();
        return pc;
    }

    pc.brushModes = function () {
        return Object.getOwnPropertyNames(brush.modes);
    };

    pc.brushMode = function (mode) {
        if (arguments.length === 0) {
            return brush.mode;
        }

        if (pc.brushModes().indexOf(mode) === -1) {
            throw "pc.brushmode: Unsupported brush mode: " + mode;
        }

        // Make sure that we don't trigger unnecessary events by checking if the mode
        // actually changes.
        if (mode !== brush.mode) {
            // When changing brush modes, the first thing we need to do is clearing any
            // brushes from the current mode, if any.
            if (brush.mode !== "None") {
                pc.brushReset();
            }

            // Next, we need to 'uninstall' the current brushMode.
            brush.modes[brush.mode].uninstall(pc);
            // Finally, we can install the requested one.
            brush.mode = mode;

            // Reference brushmode object for later use at resize() function
            brushmodeObject = brush.modes[brush.mode];
            brush.modes[brush.mode].install();
            if (mode === "None") {
                delete pc.brushPredicate;
            } else {
                pc.brushPredicate = brushPredicate;
            }
        }

        return pc;
    };

    // brush mode: 1D-Axes

    (function () {
        var brushes = {};

        function is_brushed(p) {
            return !brushes[p].empty();
        }

        // data within extents
        function selected() {
            var actives = d3.keys(__.dimensions).filter(is_brushed),
                extents = actives.map(function (p) {
                    return brushes[p].extent();
                });

            // We don't want to return the full data set when there are no axes brushed.
            // Actually, when there are no axes brushed, by definition, no items are
            // selected. So, let's avoid the filtering and just return false.
            //if (actives.length === 0) return false;

            // Resolves broken examples for now. They expect to get the full dataset back from empty brushes
            if (actives.length === 0) return __.data;

            // test if within range
            var within = {
                "date": function (d, p, dimension) {
                    if (typeof __.dimensions[p].yscale.rangePoints === "function") { // if it is ordinal
                        return extents[dimension][0] <= __.dimensions[p].yscale(d[p]) && __.dimensions[p].yscale(d[p]) <= extents[dimension][1]
                    } else {
                        return extents[dimension][0] <= d[p] && d[p] <= extents[dimension][1]
                    }
                },
                "number": function (d, p, dimension) {
                    if (typeof __.dimensions[p].yscale.rangePoints === "function") { // if it is ordinal
                        return extents[dimension][0] <= __.dimensions[p].yscale(d[p]) && __.dimensions[p].yscale(d[p]) <= extents[dimension][1]
                    } else {
                        return extents[dimension][0] <= d[p] && d[p] <= extents[dimension][1]
                    }
                },
                "string": function (d, p, dimension) {
                    return extents[dimension][0] <= __.dimensions[p].yscale(d[p]) && __.dimensions[p].yscale(d[p]) <= extents[dimension][1]
                }
            };

            return __.data
                .filter(function (d) {
                    switch (brush.predicate) {
                        case "AND":
                            return actives.every(function (p, dimension) {
                                return within[__.dimensions[p].type](d, p, dimension);
                            });
                        case "OR":
                            return actives.some(function (p, dimension) {
                                return within[__.dimensions[p].type](d, p, dimension);
                            });
                        default:
                            throw "Unknown brush predicate " + __.brushPredicate;
                    }
                });
        };

        function brushExtents(extents) {
            if (typeof (extents) === 'undefined') {
                var extents = {};
                d3.keys(__.dimensions).forEach(function (d) {
                    var brush = brushes[d];
                    if (brush !== undefined && !brush.empty()) {
                        var extent = brush.extent();
                        extent.sort(d3.ascending);
                        extents[d] = extent;
                    }
                });
                return extents;
            } else {
                //first get all the brush selections
                var brushSelections = {};
                g.selectAll('.brush')
                    .each(function (d) {
                        brushSelections[d] = d3.select(this);

                    });

                // loop over each dimension and update appropriately (if it was passed in through extents)
                d3.keys(__.dimensions).forEach(function (d) {
                    if (extents[d] === undefined) {
                        return;
                    }

                    var brush = brushes[d];
                    if (brush !== undefined) {
                        //update the extent
                        brush.extent(extents[d]);

                        //redraw the brush
                        brushSelections[d]
                            .transition()
                            .duration(0)
                            .call(brush);

                        //fire some events
                        brush.event(brushSelections[d]);
                    }
                });

                //redraw the chart
                pc.renderBrushed();

                return pc;
            }
        }

        function brushFor(axis) {
            var brush = d3.svg.brush();

            brush
                .y(__.dimensions[axis].yscale)
                .on("brushstart", function () {
                    if (d3.event.sourceEvent !== null) {
                        events.brushstart.call(pc, __.brushed);
                        d3.event.sourceEvent.stopPropagation();
                    }
                })
                .on("brush", function () {
                    brushUpdated(selected());
                })
                .on("brushend", function () {
                    events.brushend.call(pc, __.brushed);
                });

            brushes[axis] = brush;
            return brush;
        };

        function brushReset(dimension) {
            if (dimension === undefined) {
                __.brushed = false;
                if (g) {
                    g.selectAll('.brush')
                        .each(function (d) {
                            d3.select(this)
                                .transition()
                                .duration(0)
                                .call(brushes[d].clear());
                        });
                    pc.renderBrushed();
                }
            } else {
                if (g) {
                    g.selectAll('.brush')
                        .each(function (d) {
                            if (d != dimension) return;
                            d3.select(this)
                                .transition()
                                .duration(0)
                                .call(brushes[d].clear());
                            brushes[d].event(d3.select(this));
                        });
                    pc.renderBrushed();
                }
            }
            return this;
        };

        function install() {
            if (!g) pc.createAxes();

            // Add and store a brush for each axis.
            g.append("svg:g")
                .attr("class", "brush")
                .each(function (d) {
                    d3.select(this).call(brushFor(d));
                })
                .selectAll("rect")
                .style("visibility", null)
                .attr("x", -15)
                .attr("width", 30);

            pc.brushExtents = brushExtents;
            pc.brushReset = brushReset;
            return pc;
        }

        brush.modes["1D-axes"] = {
            install: install,
            uninstall: function () {
                g.selectAll(".brush").remove();
                brushes = {};
                delete pc.brushExtents;
                delete pc.brushReset;
            },
            selected: selected,
            brushState: brushExtents
        }
    })();

    pc.interactive = function () {
        flags.interactive = true;
        return this;
    };

    // expose a few objects
    pc.xscale = xscale;
    pc.ctx = ctx;
    pc.canvas = canvas;
    pc.g = function () {
        return g;
    };

    // rescale for height, width and margins
    // TODO:210 currently assumes chart is brushable, and destroys old brushes
    pc.resize = function () {
        // reference the current brushMode
        var currentBrushMode = pc.brushMode();

        // reinstalling brushes when resizing currently works for "1D-axes" and "1D-axes-multi"
        if (currentBrushMode === "1D-axes" || currentBrushMode === "1D-axes-multi") {
            //store the current brush state
            var brushModeState = pc.brushExtents();
        }

        // selection size
        pc.selection.select("svg")
            .attr("width", __.width)
            .attr("height", __.height)
        pc.svg.attr("transform", "translate(" + __.margin.left + "," + __.margin.top + ")");

        // scales
        //pc.autoscale();

        if (isBrushed()) {
            pc.autoscale();
            pc.renderBrushed();
        } else {
            pc.render();
            //pc.reRender();
        }

        // axes, destroys old brushes.
        if (g) pc.createAxes();
        if (flags.brushable) pc.brushable();
        if (flags.reorderable) pc.reorderable();

        // reinstalling brushes when resizing currently works for "1D-axes" and "1D-axes-multi"
        // createAxes() destroyed the brush elements, reinstall them and restore the brush state
        if (currentBrushMode === "1D-axes" || currentBrushMode === "1D-axes-multi") {
            // install() recreates the brush elements and their events, assigns empty brush extents
            brushmodeObject.install();
            // set the empty brush extents to the saved brush state
            pc.brushExtents(brushModeState);
        }

        events.resize.call(this, {
            width: __.width,
            height: __.height,
            margin: __.margin
        });

        return this;
    };

    pc.reset = function(){
        d3.keys(__.yscaleDomains).forEach(function (k) {
            if(__.dimensions[k] === undefined){
                return;
            }

            if (__.dimensions[k].type != "string") {
                delete __.yscaleDomains[k];
            } else {
                //keep current string domin
            }
        });
    }

    pc.update = function () {
        // reference the current brushMode
        // var currentBrushMode = pc.brushMode();
        //
        // // reinstalling brushes when resizing currently works for "1D-axes" and "1D-axes-multi"
        // if (currentBrushMode === "1D-axes" || currentBrushMode === "1D-axes-multi") {
        //     //store the current brush state
        //     var brushModeState = pc.brushExtents();
        // }

        if (isBrushed()) {
            pc.renderBrushed();
        } else {
            pc.reRender();
        }

        // axes, destroys old brushes.
        if (flags.brushable) pc.brushable();
        if (flags.reorderable) pc.reorderable();
        //
        // // reinstalling brushes when resizing currently works for "1D-axes" and "1D-axes-multi"
        // // createAxes() destroyed the brush elements, reinstall them and restore the brush state
        // if (currentBrushMode === "1D-axes" || currentBrushMode === "1D-axes-multi") {
        //     // install() recreates the brush elements and their events, assigns empty brush extents
        //     brushmodeObject.install();
        //     // set the empty brush extents to the saved brush state
        //     pc.brushExtents(brushModeState);
        // }
        return this;
    };
    // highlight an array of data
    pc.highlight = function (data) {
        if (arguments.length === 0) {
            return __.highlighted;
        }

        __.highlighted = data;
        pc.clear("highlight");
        if (__.brushed) {
            //console.log("brushed");
            d3.select(canvas.brushed).classed("faded", true);
            d3.select(canvas.foreground).classed("hidden", true);
        } else {
            d3.select(canvas.foreground).classed("faded", true);
        }

        data.forEach(path_highlight);
        events.highlight.call(this, data);
        return this;
    };

    // clear highlighting
    pc.unhighlight = function () {
        __.highlighted = [];

        pc.clear("highlight");
        d3.selectAll([canvas.foreground, canvas.brushed]).classed("faded", false);
        return this;
    };

    // calculate 2d intersection of line a->b with line c->d
    // points are objects with x and y properties
    pc.intersection = function (a, b, c, d) {
        return {
            x: ((a.x * b.y - a.y * b.x) * (c.x - d.x) - (a.x - b.x) * (c.x * d.y - c.y * d.x)) / ((a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x)),
            y: ((a.x * b.y - a.y * b.x) * (c.y - d.y) - (a.y - b.y) * (c.x * d.y - c.y * d.x)) / ((a.x - b.x) * (c.y - d.y) - (a.y - b.y) * (c.x - d.x))
        };
    };

    function position(d) {
        if (xscale.range().length === 0) {
            xscale.rangePoints([0, w()], 1);
        }
        var v = dragging[d];
        return v == null ? xscale(d) : v;
    }
    pc.version = "0.7.0";
    // this descriptive text should live with other introspective methods
    pc.toString = function () {
        return "Parallel Coordinates: " + d3.keys(__.dimensions).length + " dimensions (" + d3.keys(__.data[0]).length + " total) , " + __.data.length + " rows";
    };

    return pc;
};

d3.renderQueue = (function (func) {
    var _queue = [], // data to be rendered
        _rate = 10, // number of calls per frame
        _clear = function () {}, // clearing function
        _i = 0; // current iteration

    var rq = function (data) {
        if (data) rq.data(data);
        rq.invalidate();
        _clear();
        rq.render();
    };

    rq.render = function () {
        _i = 0;
        var valid = true;
        rq.invalidate = function () {
            valid = false;
        };

        function doFrame() {
            if (!valid) return true;
            if (_i > _queue.length) return true;

            // Typical d3 behavior is to pass a data item *and* its index. As the
            // render queue splits the original data set, we'll have to be slightly
            // more carefull about passing the correct index with the data item.
            var end = Math.min(_i + _rate, _queue.length);
            for (var i = _i; i < end; i++) {
                func(_queue[i], i);
            }
            _i += _rate;
        }

        d3.timer(doFrame);
    };

    rq.data = function (data) {
        rq.invalidate();
        _queue = data.slice(0);
        return rq;
    };

    rq.rate = function (value) {
        if (!arguments.length) return _rate;
        _rate = value;
        return rq;
    };

    rq.remaining = function () {
        return _queue.length - _i;
    };

    // clear the canvas
    rq.clear = function (func) {
        if (!arguments.length) {
            _clear();
            return rq;
        }
        _clear = func;
        return rq;
    };

    rq.invalidate = function () {};

    return rq;
});

redpajama_set_name: RedPajamaGithub


text:
Asante Kotoko Request To Change Home Venue To Aliu Mahama Sports Stadium
NEWSCAF Champions League
By Myke Alonso On Nov 30, 2020
Asante Kotoko have requested to change their home venue from the Accra Sports Stadium to the Aliu Mahama Sports Stadium in Tamale for the remainder of the 2020/2021 Ghana Premier League season, Citi Sports can confirm.
In a letter sighted by Citi Sports, the Porcupine Warriors did not state the reason for wanting to move to the Northern Regional capital where they will also be expected to host their CAF Champions League home games.
OFFICIAL: Asante Kotoko Seal Partnership Agreement With EPL…
Asante Kotoko Striker Kwame Opoku Reveals His Goalscoring…
Asante Kotoko Star Named In Ghana Premier League Team Of The…
Kotoko say CAF has approved the facility to host continental matches.
Kotoko switched to the Accra Sports Stadium following the closure of the Baba Yara Stadium for renovation works last season.
So far, they have played just one home game in the 2020/2021 season, drawing 1-1 with Techiman Eleven Wonders.
They held Mauritanian side FC Nouadibhou to a 1-1 in the first leg of the CAF Champions League preliminary qualifying round match on Sunday and will host the return leg in a week's time.
source: citinewsroom.com
Myke Alonso
As a kid, I dreamt of being a sports journalist. My journey began some years ago when I created my first sports news page on Facebook and WhatsApp called "Hot Sports" and from there on, my passion for sports journalism grew stronger. Now, here I am as an Editor-at-large for Myfabulousonline.com where I will strive to add value and learn as much as I can.
Ghana Premier League Week 3 Results, Updated Table and Top Scorers Chart
Asante Kotoko Arrive In Ghana After FC Nouadhibou Game In Mauritania
OFFICIAL: Asante Kotoko Seal Partnership Agreement With…
Asante Kotoko Striker Kwame Opoku Reveals His…
Asante Kotoko Star Named In Ghana Premier League Team…
Ghana Premier League Week 9 Results, Updated Table and…
Asante Kotoko Player Ratings As Gama Bright In WAFA,…
Highlights: WAFA 1-1 Asante Kotoko
VIDEO: Watch Kwame Opoku's Sixth Goal Of The Season…
Muniru Starts, Opoku Dropped As Asante Kotoko Name Starting…
This Is How Asante Kotoko Could Line Up Against WAFA SC…
WAFA vs Kotoko Preview: How To Watch On TV, Key Players,…


HOUGHTON, Mich. – The Lake Erie College women's basketball team was defeated by Michigan Tech today (January 8th), 75-35. With the loss the Storm falls to 7-6 overall and 2-5 in the conference and with the win the Huskies improve to 10-1 overall and 6-1 in conference play.
The game started as a back and forth battle until the first media timeout, with the Storm trailing by three, 12-9. Senior forward Chloe Irish (LaGrange, Ohio / Keystone) led the way with five points in the first five minutes, highlighted by a three pointer off an assist by junior guard Sami Narducci (North Royalton, Ohio / North Royalton). The Huskies stretched the lead to 23 at the half as they went on a 26-6 run, that started after the first media timeout and went through the end of the first half.
The second half started with both teams trading buckets as the Huskies led by 26, 47-21 at the first media timeout of the second half. Michigan Tech went on an 11-0 run that widened the margin to 34 points with 7:16 to play in the game. The Huskies run was ended by a Lake Erie timeout, and the Huskies went on to win the game by 40 points, 75-35.
Irish, junior center Kaeding Skelton (Grand Haven, Mich. / Grand Haven), and sophomore guard Brianna Shagovac (Lorain, Ohio / Amherst Steele) led the way for Lake Erie will seven points each. Narducci led the way with four assists in the game for the Storm, and junior guard Shelby Carpenter (Dayton, Ohio / Miami Valley) grabbed six rebounds, and added four points for Lake Erie. Sophomore guard Daija (Cleveland, Ohio / St. Joseph Academy) Jones had six rebounds off the bench for Lake Erie.
The Storm will be back in action Saturday (January 10th) when they travel to take on Northern Michigan at 1 P.M.


text:
Desktop Metal qualifies commercially pure copper for Production System
Desktop Metal has qualified commercially pure copper for use with its Production System, enabling parts requiring conductivity – such as liquid cooling plates (above) – to be manufactured as a single component (Courtesy Desktop Metal)
Desktop Metal, Boston, Massachusetts, USA, has qualified C10300, commercially pure copper with over 99.95% purity, for use on the Production System™ platform, which utilises the company's Single Pass Jetting™ (SPJ), a form of Binder Jetting (BJT) technology. Due to copper's excellent thermal and electric conductivity, this addition is expected to widen the scope of SPJ technology into the production of high-performance parts at scale across a broad variety of industries, including automotive, aerospace and electronics.
"Copper has been a highly requested material from many of our customers and prospects, and has applications spanning a broad variety of industries, from thermal hardware found in air and liquid cooling systems to conformally cooled coils for transmission of high frequency currents," stated Jonah Myerberg, co-founder and CTO. "We are excited to be able to expand our extensive Production System materials portfolio to support customers looking to 3D print electrically and thermally conductive components at scale and at a fraction of the cost of conventional manufacturing methods."
One application highlighted by the company is the additive manufacture of liquid cooling plates, used to regulate temperatures on high-performance microprocessors. While traditional production methods require the parts to be made from multiple components, the BJT technology employed by the Production System builds the plates as single pieces. This enables hundreds of cooling plates to be additively manufactured per day, now from a material that is said to maximise the heat dissipation from the electronic chip to the cooling fluid.
As well as for cooling plates, commercially pure copper is reputed to be an ideal material for any application which requires heat or electricity transfer, such as pucks and manifolds, heat sinks, heat exchangers, and bus bars used in power-intensive electrical applications.
www.desktopmetal.com
Höganäs AB, Sweden, has announced that Fredrik Emilson has stepped down as its president and CEO of the company. Until a successor has been appoi...»
Half of iPhones could be made in India by 2027
Half of all iPhones could be manufactured in India by 2027, progressing Apple's move away from its reliance on a single-country supply that had a...»
Arburg celebrates 100 years during Anniversary Days 2023
Arburg GmbH + Co KG, headquartered in Lossburg, Germany, is celebrating its centenary this year, and plans to recognise this important milestone wi...»


text:
The team at Scribe Winery isn't just making some of the best wine in California today, they are doing it with style. Scribe has quickly built a reputation or hospitality, boasting a brilliant tasting room at the southern tip of Sonoma Valley with a literary theme and a rustic vibe. The front lawn provides a relaxed atmosphere to sip the wines and take in panoramic views of Carneros to the south. But it's all just window dressing if the juice in the bottle isn't up to par...and the the good news is, the wines are even better than the views.
Every wine, in every vintage, sees its own tailor-made winemaking program. Fermentations are often long and slow; malolactic is often blocked; and the percentage of new oak is kept to a minimum. The aim is to allow the vineyard to express itself through the wine, with particular emphasis on a savory flavor profile. These wines are built for the dinner table. Or the picnic table, depending on your preference. No matter where you enjoy them, we think you'll find the Scribe wines among the most exciting being produced on the west coast today.
The estate vineyard comprises 50 planted acres in the middle of a 250acre converted turkey farm. Sylvaner and Riesling are the primary varieties here. The vines are farmed organically, and produce wines that are distinctly California but unique entities unto themselves. Beyond that, owners Adam and Andrew Mariani have access to incredible sites in Carneros and beyond. Their Cabernet Sauvignon hails from a 5-acre piece on Atlas Peak, nearly 100 feet above sea level.


Here's energetic and fast one-minute percussion track. It contains elements of breakbeat, drum n bass and industrial music. This track is great choice for short energetic teaser montage, technology and soccer, street art and viral marketing campaign, fashion reviews, car presentation, discount action advertising and more. Archive contains full version (1:00) in WAV and MP3.


Searching for a job in Erie area? Apply for jobs in or near Erie CO, jobs in Boulder County and throughout Colorado. Post jobs for free: Job posting site for Erie employers/ recruiters listing new employment opportunities, full time/ part time job boards, local city/State job openings, internships. Find employees- free resume search.


Mixed-income housing and neighborhoods are commonly advanced as a method of alleviating the harms of concentrated poverty and achieving urban revitalization. A 2013 literature review, published in Cityscape, clarifies the hypothesized benefits of mixed-income communities, examines the state of the evidence, and considers potential next steps for reducing economic segregation.
The hypothesized benefits of mixed-income living have included poverty alleviation, increased property values, an increased tolerance for diversity for residents of all incomes, and improved housing quality, services, and neighborhood conditions for lower-income residents. The evidence generally supports the hypotheses regarding neighborhood improvements, but not those related to social interaction and poverty alleviation.
Economic desegregation does not, on its own, lead to meaningful interactions between neighbors across economic groups.
Community events and facilities may reinforce socioeconomic divisions if one income group feels more of a claim on the space.
Relationships between residents may change over time, either as residents become more comfortable with each other or as residents give up and retreat to their comfort zones.
Mixed-income communities have not generates the hypothesized improvements in economic well-being for low-income households. While some evidence suggests an increase in employment, the evidence is weak at best about income benefits.
Achieving economic improvements will likely require changes in school quality, job supports, and other factors. Benefits may also accrue over a longer period of time than previously studied.
Residents of mixed-income developments report satisfaction with housing quality, neighborhood services, and public safety.
Moving to a mixed-income community appears to have psychological benefits for low-income residents, namely in mental health improvements and the reduction of stress related to neighborhood safety concerns.
Children may experience educational, health, and behavioral benefits from moving to a lower-poverty or income-diverse area.
Mixed-income communities offer low-income households an improved sense of safety and security, but intentional and specific services and supports are necessary for addressing poverty.
The design of the public space may increase residents' interactions.
If resident organizations are structured to serve separate community populations, resident interactions across socioeconomic status are likely to be impeded.
Grocery stores and other resources in the surrounding area create additional opportunities for resident interaction.