Unsurprisingly, I signed up as well convinced a few of my friends to participate in the annual Consortium for Mathematics and Its Applications Mathematical Contest in Modelling. Typically, the committee poses a selection of problems to which undergraduate students develop, test and write a mathematical solution.
There was a special addition to this year's line-up, one of the problems incorporated Big Data. The challenge was to devise a donation strategy for a post-secondary education charity. The most interesting aspect was designing an appropriate return on investment. The available data sets were U.S. National Center on Education Statistics and College Scorecard data set.
While the committee supposedly provided snapshots of data, our team quickly realized the data was too incomplete for the problem at hand. We set out to collect the required variables for nearly 7000 schools.
A teammate collected all the relevant data, filtered out smaller schools, specific designations, and level of institution. The goal was to have a uniform set of school to avoid skewing the ranking system.
We created a benchmark of the top 10 schools, who had lowered the poverty rate for students coming in. Post-secondary education is often seen as the class-equalizer providing opportunities for individuals to guarantee higher annual income. Therefore we picked the schools that performed the best in
A simple relative change formula was used and the schools with the highest score placed top of the list. Then the other schools on the list were compared to the benchmarks and classified into ten different clusters. The variables values were also normalized.
We created a conceptual return on investment (ROI) based on the school’s effectiveness on alleviating poverty. Read more in our report here!
Sources
COMAP 2016 - Problem C Description
GitHub Repo for Project


Implements two tests for same-source of toolmarks. The chumbley_non_random() test follows the paper "An Improved Version of a Tool Mark Comparison Algorithm" by Hadler and Morris (2017) <doi:10.1111/1556-4029.13640>. This is an extension of the Chumbley score as previously described in "Validation of Tool Mark Comparisons Obtained Using a Quantitative, Comparative, Statistical Algorithm" by Chumbley et al (2010) <doi:10.1111/j.1556-4029.2010.01424.x>. fixed_width_no_modeling() is based on correlation measures in a diamond shaped area of the toolmark as described in Hadler (2017).
| Version: | 0.0.1 |
| Depends: | R (≥ 3.3), plyr (≥ 1.8.4), dplyr (≥ 0.7.2), reshape2 (≥ 1.4.2) |
| Imports: | ggplot2 (≥ 2.2.1) |
| Published: | 2018-01-16 |
| Author: | Jeremy Hadler [aut, cre], Max Morris [ths], Heike Hofmann [ctb] |
| Maintainer: | Jeremy Hadler <hadler13 at yahoo.com> |
| License: | GPL-3 |
| NeedsCompilation: | no |
| CRAN checks: | toolmaRk results |
| Reference manual: | toolmaRk.pdf |
| Package source: | toolmaRk_0.0.1.tar.gz |
| Windows binaries: | r-devel: toolmaRk_0.0.1.zip, r-release: toolmaRk_0.0.1.zip, r-oldrel: toolmaRk_0.0.1.zip |
| OS X binaries: | r-release: toolmaRk_0.0.1.tgz, r-oldrel: toolmaRk_0.0.1.tgz |
Please use the canonical form https://CRAN.R-project.org/package=toolmaRk to link to this page.


George Uno
Nick Otter
https://github.com/minton/Spot/pull/11
def sendText(to, from, message)
@client = Twilio::Rest::Client.new account_sid, auth_token
@client.account.messages.create(
:from => from,
:to => to,
:body => message
)
end
sendText("+15551234567", "+15555671234", "Happy Birthday!")


{{ content }}
{% include head.html %}
{% include header.html %}We provide cutting-edge information security services
Are you evaluating your IP portfolio before cross-licensing negotiations, or looking to put an experienced expert on the witness stand?


The Cali or Bust Conundrum
A recent study highlighted the brain drain problem for tech talent in Canada. In this post, I will explain the ‘Cali or bust’ movement and describe its effect on the tech brain drain. In addition, I will provide 8 recommendations to retain and attract top Canadian tech talent.
Brain Drain Report
A study led by Zachary Spicer, found that 25% of recent tech grads from Canada were working in the US. To summarize the study, the team collected data from 3,162 LinkedIn profiles of graduates from University of British Columbia (UBC), University of Waterloo (UW), and University of Toronto (U of T).
It is important to note that 52% of this sample size were UW graduates in Software Engineering (SE), Electrical & Computer Engineering (ECE), Systems Design Engineering (SYDE), Computer Science (CS), and Mathematics. These programs are all highly competitive and generally require students to complete 5 or 6 co-op terms. Engineering Science, ECE, and CS graduates from U of T and UBC make up most of the remaining data points. These programs are also highly competitive and offer co-op or PEY opportunities.
Based on these facts, it would be far from the truth to extrapolate the report results to Canada as a whole. The University of Waterloo is the #1 feeder school to Silicon Valley and large US tech companies. Given that UW grads represents the majority of the sample, it would be extremely unfair to make any conclusions about Canada STEM students in general. A more accurate phrasing would be “25% of recent SE/CS/ECE graduates from Canada’s top undergrad programs such as UW are working in the US”.
I personally think that the Canadian tech brain drain problem is being overblown, as these results do not represent Canada collectively. However, I do believe that at UW specifically, brain drain is a major problem. For the remainder of this post, I will be focusing solely on analyzing brain drain at UW.
What is ‘Cali or bust’?
‘Cali or bust’ is a catch phrase and meme that was popularized on /r/uwaterloo in mid-2016. There is a general misconception that this maxim means “I must only consider and get an internship offer in California or else I have failed”. For most students, a more accurate interpretation is “I will try my best to get an internship in the US or at a well-known US tech company. I will use more than half of my co-op applications for these competitive roles in the main round. If I ‘bust’ in the main round, I will open up my options for the continuous round.” Despite not being located California, Google Waterloo, Bloomberg NYC, and Amazon Toronto are all considered ‘Cali’ in the mentioned maxim.
Cali or bust: When you use most of your co-op applications for competitive US companies. ‘Cali’ = receiving an internship offer for a competitive US company. ‘Bust’ = failing to get ‘Cali’.
The main reasons for why a student would ‘Cali or bust’ are: higher internship pay in the US, experience new locations & cultures, work at reputable companies, and the fact that the many of their classmates are also heading to the US.
Consequences of ‘Cali or bust’
The winners of the ‘Cali or bust’ movement are UW students, US tech companies, and UW. The losers are: UW students, Canadian tech companies, the Canadian tech industry, and the government.
For students, ‘Cali or bust’ isn’t regarded as a negative mindset to have. UW students should be able to pursue whatever opportunities maximize their potential. It just happens that the majority of these opportunities are located in the US. As mentioned before, there are countless reasons why a UW student would consider ‘Cali or bust’. There is little to none real incentive for a UW student to not ‘Cali or bust’.
The tech industry in Silicon Valley is the equivalent of the film industry in Hollywood.  Silicon Valley and Hollywood are the world’s largest supercluster of opportunities for their respective industries. Opportunities in the US vs. Canada is like comparing the NFL to the CFL. The former is far more reputable and prestigious than the latter; the difference in salaries is also quite significant. Of course, in both examples, it’s important to note that there are still excellent opportunities outside of the industry leader.
Finally, UW’s co-op program provides a perfect gateway for students to ‘Cali or bust’. It’s very common for CEOs and engineering leaders of US companies to fly into Waterloo to recruit students. For reference, here’s the employer info session calendar.
Unfortunately, at the same time, UW students can also be losers. ‘Cali or bust’ also promotes a toxic competitive environment amongst students, where co-op jobs that are not ‘Cali’ may be considered inferior. This creates a detrimental effect to many students’ self worth when they ‘bust’.
At the end of the day, the only clear, real winners of ‘Cali or bust’ are the US tech companies.
Why UW students work in the US after graduation
When I was an SE student, over 60% of my class worked in the US for their 5th co-op term. For new grad roles, this number will be in a similar ballpark. Amongst the CS/SE/ECE/SYDE programs at UW, over 30% of new grads will work in the US.
The #1 reason why UW students move to the US is the massive difference in total compensation, which I previously wrote about here. After considering taxes and cost of living, your take-home income can be 50 to 100% higher in the US compared to Canada.
Other reasons include: company reputation, scope of work, professional development, peers, location preferences, and personal factors.
The ‘Cali or bust’ movement for getting the best internships directly affects the UW brain drain problem. For full-time opportunities, students are likely to return to an employer from their final 3 co-op terms. For example, Facebook is known to offer a 75K USD signing bonus for returning interns, which is higher than many Canadian companies’ salaries. When an exceptional full-time offer is thrown at you, and combined with an expiring deadline, it’s extremely hard to even consider opportunities in Canada.
In short, the ‘Cali or bust’ movement is the primary driver of migration. If a student has interned in the US, they’re much more likely to return to the US. If a student has only interned in Canada, then they’re more likely to remain in Canada.
As more and more students successfully achieve ‘Cali or bust’, the movement compounds into increasing brain drain for UW graduates.
Recommendations
To reduce UW’s brain drain, the onus is on Canadian tech companies and the university. I have come up with the following recommendations to address the problem.
Co-op jobs
First and foremost, Canadian tech companies must significantly improve their internship programs. By retaining students in Canada for their final internships, they are more likely to remain after graduation.
1: Increase the salary of senior co-op jobs to at least CAD $40 per hour.
For students, a short term goal is to pay for next term’s tuition and reduce student loan. Co-op jobs in Canada currently pay on average CAD $26 per hour, whereas US employers pay students USD $40 per hour, and also offer generous housing stipends. A US co-op job is even more competitive when you consider the USD to CAD exchange rate. To satisfy a student’s short term financial goals, it’s critical to increase the salary of top Canadian co-op jobs. For Canadian tech companies, increasing co-op salaries can lead to increases in the quantity and quality of talent, as well as intern to full-time conversions.
2: Incentivize former interns to return for another internship in their final terms.
One excellent tactic I’ve learned about is PagerDuty’s return intern offer. Former interns who return to PagerDuty for their last co-op term receive a $10,000 one-time bonus. This seems to work well for them, as many new full-time engineers are direct intern conversions. Microsoft also does a similar tactic by offering returning interns a $5,000 one-time bonus. Incentives can also be responsibility based. For example, Canadian tech companies can offer interns to work on more senior technical projects and provide invaluable learning opportunities.
3: Get engineering directors to sell an intern on returning for full-time.
As an intern, I would appreciate having an engineering director sell me on returning full-time over a recruiter. Most Canadian companies cannot offer a compensation package that is competitive to US companies. This means that it’s crucial for a director to sell the intern on the impact and professional development they will experience. The time commitment could be as little as a 30 minute 1 on 1 with the intern.
Full-time compensation
4: Increase total compensation by offering stocks/equity/options.
If increasing salary is not possible, then Canadian tech companies should be prepared to offer long-term compensation bonuses to be competitive with US companies. Stocks/equity/options also help the employee feel more personally invested into the company. Perhaps, the government can consider investing into a one-time grant for companies to provide a signing bonus for co-op students beginning their first full-time job.
International students
About a quarter of CS/SE students at UW are international students. UW graduates who are Canadian citizens currently have the privilege of working in the US easily via the TN visa. However, for international students, acquiring an H1B visa to work in the US is very difficult.
5: Target international students and retain them in Canada for full-time opportunities.
Canadian tech companies can take advantage of international students’ visa situation by investing into recruiting them. From the discussions I’ve had with my friends who are international students, they all seemed very impressed with Canada as a country. Tech companies can sell international students on the roadmap to getting a Canadian permanent residence. Similarly, from orientation week to the graduation ceremony, UW should be proactively convincing and supporting international students to remain in Canada.
US satellite offices
6: Welcome more US satellite offices.
Some great examples are Google Waterloo, Amazon Vancouver, and Facebook Montreal. Although US companies will steal potential tech talent from nearby small and mid-sized companies, it does provide lucrative opportunities for UW graduates to pursue. The government should be proactive in welcoming new US satellite offices due to the well-paying jobs created, and the net increase in tech talent retained.
Re-acquiring Canadian tech talent from the US
In addition to retaining graduates, another important goal is to re-acquire Canadian tech talent that migrated to the US. A common theme in my conversations with UW graduates and friends is that they expressed strong interest in wanting to return to Canada in the future.
7: UW should proactively sell alumni into returning to Canada.
The UW communications team should be communicating the state of Canadian tech to alumni on an annual basis. For alumni who have spent years in the US, they are likely to be out of touch with what’s happening in the world of Canadian tech. For in-person events such as the 5 and 10 year alumni reunion, UW needs to send a strong message to welcome alumni back home.
8: Tech companies should target senior engineers and leaders in the US, and sell them on “coming home” and taking on additional responsibility.
This blog post is an excellent example of a Canadian startup convincing an engineering leader from the US to join them. Although Canadian tech companies won’t be able to match the candidate’s previous compensation, what they can do is selling them on the company’s vision and values. They can also sell the candidate on ‘levelling up professionally, i.e. taking on additional technical or management responsibility. Recruiters and engineering leaders at Canadian tech companies should proactively target UW alumni who have gathered 5-10 years of experience in the US and sell them into “coming home”.


Book:
Known Info: {[{ 'Book:' + book + ' Movie: ' + movie }]}
{[{ x }]}
Visited Places:
{[{ x.place + 'in the year ' + x.year }]}


This encryption algorithm invented by Caesar only shifts the letters of the alphabet.
The key for the Caesar encryption algorithm is entered in the Key entry Caesar / Rot-13 dialog.
Characters which are not part of the alphabet are normally left out of the encrypted text, so that after decryption these characters have to be inserted from the textual context. This applies to both punctuation characters and special characters (especially spaces between two words). The menu selection Options \ Text Options is used to specify whether punctuation and special characters should be retained during encryption and decryption. Which characters build up the alphabet can be selected in the Text Options dialog.
Under the Caesar encryption algorithm, one character from the alphabet is used as a key. Depending on the position of the letter, the letters of the plaintext are shifted in repeated cycles (the sequence of characters in the alphabet to be used is specified in the Text Options dialog). If the alphabet consists only of upper case letters (this is the classical case), a cyclical shift of one character takes place when "A" is entered, two characters for "B" ... 26 characters for "Z". To decrypt the text, the encrypted text is simply shifted in the other direction.
Example (classical case, alphabet of 26 letters, first letter A has the value 1, key is C):
If the key is "C", all the letters are cyclically shifted by three places.
| Plaintext | Encrypted Text |
| A | D |
| B | E |
| C | F |
| ... | ... |
| W | Z |
| X | A |
| Y | B |
| Z | C |
Remark:
The letter "Z" should not be used as the key, as in this case the "encrypted"
text is identical to the plaintext.
A special case of Caesar is the so called Rot-13 encryption, which is used in chat rooms and news groups. Rot-13 shifts each character by 13 places, corresponding to a Caesar encryption with key "M". Repeated twice Rot-13 yields the plaintext again.
An advancement of the Caesar cipher is the Vigenère cipher.
The Caesar encryption algorithm can be broken relatively easily with a Ciphertext Only attack (see Automatic analysis, Caesar encryption algorithm). An example of this will be found in the Examples chapter.


"Hardware Setup Instructions
On the top of the board there are two solder jumpers which need to be connected before emonTx Shield can operate. To make connection the middle solder pad should be connected with a blob of solder to either the left of right solder pad, depending on the connection required. The solder can be re-melted and adjusted at a later date if required."
i am using arduino UNO so which two solder jumpers are needed to be connected. i expect there is photo that might explain this more clearly.
in addition, i have basically soldered every component on the PCB already except for the RM128 , i guess it is only used for transmitting data wirelessly , therefore i can just use the arduino software to display the measured current and voltage on my computer before moving on to the wireless transmission. is that correct?
Re: soldering
I've not used this board, but it appears that the two solder jumpers are only to do with the RF chip. If you're not using the RFM12B facility yet, then I would expect the circuit to behave correctly without either solder jumper being made.
To check that your new hardware is behaving as expected, you may find it helpful to run some of the sketches that appear near the top of my Summary Page. RawSamplesTool_4ss_2 will provide a one-shot graphical display of your voltage and current waveforms via the Serial Monitor. This will show how well your system is set up for the appropriate range of powers that you wish to measure. MinMaxAndRangeChecker will repeatedly display relevant data for analogue inputs 0 to 3. For any of these inputs that are floating, the displayed data should be ignored.
With four CT inputs and a voltage sensor, the emonTx Shield appears to be using five of the six available analogue inputs. The tool could be easily extended to match this arrangement.
Re: soldering
chunyang: I told you in this thread where those links are. Ask yourself, why should we waste time answering your questions if you do not care to read the answers?
Re: soldering
I think chungyang was simply wanting to confirm that his emonTxShield + Arduino Uno will work OK without the RF chip being fitted, and without doing anything to either solder jumper. This scenario is not covered specifically by the online notes, so asking for a second opinion on the forum seems a reasonable thing to do.
When the RFM12B is to be included, the online guide notes for the two solder jumpers will no doubt be of use.
Re: soldering
thank you you understand what i am asking..


Async::Node
Represents a node in a tree, used for nested class Async::Task
instances.
Definitions
def initialize(parent = nil, annotation: nil, transient: false)
Create a new node in the tree.
Implementation
def initialize(parent = nil, annotation: nil, transient: false)
@parent = nil
@children = nil
@annotation = annotation
@object_name = nil
@transient = transient
@head = nil
@tail = nil
if parent
parent.add_child(self)
end
end
attr_accessor :head
You should not directly rely on these pointers but instead use #children
.
List pointers:
attr :parent
attr :children
attr :annotation
A useful identifier for the current node.
def children?
Whether there are children?
Implementation
def children?
@children != nil &&<EMAIL_ADDRESS>end
def transient?
Is this node transient?
Implementation
def transient?
@transient
end
def parent=(parent)
Change the parent of this node.
Implementation
def parent=(parent)
return if @parent.equal?(parent)
if @parent
@parent.delete_child(self)
@parent = nil
end
if parent
parent.add_child(self)
end
return self
end
def finished?
Whether the node can be consumed safely. By default, checks if the children set is empty.
Implementation
def finished?
@children.nil? || @children.finished?
end
def consume
If the node has a parent, and is Async::Node#finished?
, then remove this node from
the parent.
Implementation
def consume
if parent = @parent and finished?
parent.delete_child(self)
if @children
@children.each do |child|
if child.finished?
delete_child(child)
else
parent.add_child(child)
end
end
@children = nil
end
parent.consume
end
end
def traverse(level = 0, &block)
Traverse the tree.
Implementation
def traverse(level = 0, &block)
yield self, level
@children&.each do |child|
child.traverse(level + 1, &block)
end
end


a
(directive in module ng
)
Modifies the default behavior of html A tag, so that the default action is prevented when href attribute is empty.
The reasoning for this change is to allow easy creation of action links with ngClick
directive
without changing the location or causing page reloads, e.g.:
Save
This directive can be used as custom element, but we aware of IE restrictions.
as element:


{% extends "imagersite/base.html" %} {% load thumbnail %}
It's like Instagram, but significantly worse. Your personal details will probably be stolen and sold for Bitcoin. Register below!
{% thumbnail photo.imgfile "720x720" crop="center" as im %} {% endthumbnail %} {% if user.is_authenticated %}Logout Change Password {% else %} Login Register


NUNS ON THE RUN A film review by Randy Parker Copyright 1996 Randy Parker
RATING: **1/2 (out of ****)
(Review written in 1990)
There are only a few contemporary actors who can make fans laugh simply by appearing on screen. These actors don't have to do anything funny; just looking at them brings on the giggles. Woody Allen and John Cleese are prime examples, and if you ask me, so is Eric Idle, who--unlike Cleese--has been woefully underutilized by filmmakers since Monty Python disbanded.
Finally, seven years after MEANING OF LIFE, Idle has a starring role (opposite Robbie Coltrane) in NUNS ON THE RUN.
Idle and Coltrane play aging crooks who are looking to go straight. As the title suggests, they end up hiding in a convent, disguised as nuns. Idle, who is no stranger to appearing in drag, brings his customary flair to the role. Coltrane, as Idle's partner in crime, plays his part well, but he doesn't have Idle's comic pizazz. Camille Coduri, who plays Idle's love-interest, is adorable in a Goldie Hawn sort of way.
Writer-director Jonathan Lynn throws gag after gag at the screen, and only some of them stick. The movie's appeal derives more from the comic performances than from Lynn's uneven screenplay, which relies too much on cheap, physical humor. NUNS ON THE RUN is no FISH CALLED WANDA, but it's nearly impossible to resist Eric Idle as a nun.
--- Randy Parker<EMAIL_ADDRESS>http://www.shoestring.org
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


| Unique ID |
Date |
Client Name |
Project Name |
Impact |
Status |
Action |
|
|
05/06/2021
|
Connor
|
project type
|
category
|
Pending
|
|
|
|
05/06/2021
|
Connor
|
project type
|
category
|
Pending
|
|
|
|
05/06/2021
|
Connor
|
project type
|
category
|
Pending
|
|
|
|
05/06/2021
|
Connor
|
project type
|
category
|
Pending
|
|


It's all about the motion.
Drag this link to your bookmarks bar: MW
Then click it on a Wikipedia page.


Halloween (1978) A film review by David Wilcock (C)1997 David Wilcock
Starring Jamie Lee Curtis and Donald Pleasence Directed By John Carpenter (The Thing, Escape from New York) A Compass Films Production.
In this likeable slasher movie, a seriously disturbed boy (who, although he's called Michael Myers, has nothing to do with the Mike Myers of Waynes World's fame!) kills his sister, gets locked up in a mental home, and, thirty years later, escapes, ready to terrorise his neighbourhood again. Pleasence knows about him and tries to stop him, Curtis soon learns about him and tries to stop it.
The film is standard jumpy fare. It's the sort of film where the lead character would see something rustling behind the bushes, would walk up to the bush slowly, would look round the bush slowly...and.....there's nothing there! S/he, of course would then turn around, and bump into the local sheriff/old guy/kid, giving the hero, and the audience, a short scare. The film does this well. The audience gets nervous because they don't know if something will jump out the bushes/cupboard/door.  In theory this should be very tacky, but Carpenter directs it in such a way, and the music plays scarily throughout, you can't help but feel a little nervous and scared.
Sadly, however, the ending can't hold up. It's silly, and not very scary. In fact, I thought the ending took an easy route out, and left itself open for a sequel (which, of course, they have been loads of). In fact, like The Game, the ending let down the film a bit. However, I still recommended this, especially if you get a big group of friends, turns the lights out, and make silly noises throughout.
Overall Rating=***1/2 out of ***** Review By David Wilcock
David Wilcock<EMAIL_ADDRESS>Visit the Wilcock Movie Page at... http://wilcockmovie.home.ml.org -OR- http://www.geocities.com/hollywood/9061
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


menu
ABOUT US
LOGIN
REGISTER
ABOUT US
LOGIN
REGISTER
Source
Destination
Container
Date
Select what you are looking for?
Search
Showing 10 results from 10 shipping lines
Source
Duration
Destination
Fright/Container
JPNV
5 Days
$0.87Delhi
USD 500
View Shipping Line
JPNV
5 Days
$0.87Delhi
USD 500
View Shipping Line
Other related combinations


Architectural Decisions
"Architecture represents the significant design decisions that shape a system,
where significant is measured by cost of change."
-- Grady Booch
In real architecture it is obvious, when thee foundation is completed and the stories of your building rise, there's no way to swap out the foundations without demolition and starting over.
In software architecture it is less obvious, but nevertheless similar important not to send in the demolition crew half way into delivery.
While in construction you demolition crew easily can be identified by hard hats, orange vests and heavy machinery, your software demolition crew often comes disguised as concerned stakeholder questioning fundamental decisions over and over (out of a variety of motives). So it is paramount to document your archtectural decisions well.
Decisions, Justification, Alternatives, Impact
Our typical architecture decision documentation starts, duh, with the table of content (unless that sits in a sidebar) and an overview of your architecture. One or more diagrams to provide an overview are well placed here.
Now number the decisions, so they can be refered to by their shortform (e.g AD45) rather than their full title. For larger or delicate system, you want to place each decision on their own page, not at least to be able to extract one (as PDF) for customer sign up. While it is tempting to use a word processor, I'd argue to use an engineering format like markdown or, when complexity justifies it, DITA. Document format and storage could be considered primordial architectural decisions.
Each decision needs to provide four elements:
- Decision
What have you decided. A factual statement. Something along the line "Our choosen programming language is COBOL" - Justification
Outline why. It should cover features, cost, skills. You don't need to state why the alternative failed in your considerations - Alternatives
What have you looked at, what made you reject the alternative possibiliy. We need to be careful, analysis paralysis lurks here. There is always another framework, language or database you could consider. This is also the area where our "friendly" demolition crew will try to stall us - Impact
Serves are a reinforcement of Justification, but extends, when appropriate, on potential risk and its mitigation. It is an important section, nevertheless our "Reichsbedenkenträger" (loosely translated as "Imperial wardens of concern") lurk here. So stay concise to the point. You don't write a PHD thesis here.
Depending on the impact of the system (malefunktion threatens life, threatens assets or requires to hit reload in the browser) you need to spend more or less time on it. For a refresher on this concepts, have a look at Crystal Clear page xvi in the preface.
Where to store them?
The best documented decisions are useless when nobody find them. So somewhere in OneDrive, Sharepoint or Jira, they most likely they are lost.
We want to keep them close. I use 2 places, depending on the project. In maven based projects, the Maven Site Plugin allows to store the entire documentation, written in markdown, in /src/main/site
(supports other formats too), while in other projects the /docs
folder will do. GitHub pages and the Just-the-docs skin render them nicely.
In other words: Our documentation lives inside the source repository
Signoff
It gets a little tricker when decisions need to be signed off. In the traditional approach that would be a word document, printed out and signed with a pen (shudder).
A more modern approach would be digitally signed PDF documents (real digital signatures, not the fancy PDF graphics).
Both solutions are wanting in storage and findability (Sharepoint anyone?), so I'd rather recommend a professional solution. This doesn't preclude your living document to stay in your version control system
As usual YMMV
Posted by Stephan H Wissel on 07 September 2020 | Comments (0) | categories: Software


Kyle MacDonald
Research Scientist, McD Tech Labs
<EMAIL_ADDRESS>Los Angeles, CA
I am a Research Scientist at McD Tech Labs working to develop artificial systems that communicate using natural language.
Before working at Tech Labs, I was a Postdoctoral researcher in the Department of Communications at the University of California, Los Angeles where I worked with Anne S. Warlaumont in the Emergence of Communication Lab. I completed my PhD at Stanford University, working with Michael Frank in the Language and Cognition Lab and with Anne Fernald and Virginia Marchman in the Language Learning Lab.
Representative publications:
-
MacDonald, K., Marchman V.A., Fernald, A., & Frank, M.C. (under review). Children flexibly seek visual information during signed and spoken language comprehension. [Preprint PDF] [code repository]
-
MacDonald, K. LaMarr, T., Corina, D., Marchman V.A., & Fernald, A. (2018). Real-time lexical comprehension in young children learning American Sign Language. Developmental Science [PDF] [Preprint PDF] [paper site] [code repository]
-
MacDonald, K., Yurovsky, D., & Frank, M.C. (2017). Social cues modulate the representations underlying cross-situational learning. Cognitive Psychology. 94, 67–84. [Preprint PDF] [code repository] [paper site]
-
MacDonald, K., Schug, M., Chase, E. & Barth, H. (2013). My people, right or wrong? Minimal group membership disrupts children’s selective trust in testimony. Cognitive Development, 28, 247-259. [PDF]


Condensing lessons learned, and important topics
This is not a Design Patterns talk
but we will touch on some of them
Requirements gathering. Talk to the client and factor out the use cases.
What is your program? What will it not do? What problem is it trying to solve?
Compose a narrative of the individual use cases. (helpful for BDD (Behat))
Go through the narrative and highlight nouns (person, place, thing), as classes
verbs (actions), as methods / behaviours (PHPSpec helps with this)
Maybe create a UML diagram - it helps you visualise the system and its relationships
Factor out commonalities - create hierarchies (base types)
putting things into your composer post-install-scripts that boot up your app’s kernel
loads services and dependencies that aren't loaded yet (redis server doesn't exist)
vagrant images php7dev(https://github.com/rlerdorf/php7dev)
docker images for any version you like
set them up at different hostnames
Scan your software with PHAN (https://github.com/etsy/phan)
manual, unit, integration, acceptance, end-to-end tests
sudo ab -n 10000 -c 100 https://php5.myapp.com
sudo ab -n 10000 -c 100 https://php7.myapp.com
Controllers are easy to mess up, create high technical debt
Use Controller Factories - don't use ServiceLocator or Container
namespace MyModule/ControllerFactory;
use \Zend\ServiceManager\FactoryInterface;
use \Zend\ServiceManager\ServiceLocatorInterface;
class MyControllerFact implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$sm = $serviceLocator->getServiceLocator();
$depA = $sm->get('depA');
$depB = $sm->get('depB');
$controller = new \MyModule\Controller\MyController($depA, $depB);
return $controller;
}
}
// app/config/services.php
$container->setDefinition('app.hello_controller', new Definition(
'AppBundle\Controller\HelloController',
array(new Reference('request'), new Reference('templating'))
));
# app/config/services.yml
services:
app.hello_controller:
class: AppBundle\Controller\HelloController
arguments: ['@request', '@templating']
class HelloController
{
public function indexAction(Request $request, Templating $tpl)
{
$vars = $request->post;
$name = $vars->name;
return $tpl->render('....', compact('name'));
}
}
You can mock out your whole system, and test the controller + templating layer
Without needing to use Selenium
BlogController::indexAction(), BlogController::updateAction(), BlogController::deleteAction()
BlogIndexAction, BlogUpdateAction, BlogDeleteAction
but it didn't really fit what we're doing
Action -> Domain -> Responder
Action/ BlogIndexAction.php BlogCreateAction.php Domain/ # Model, Gateway, Mapper, Entity, Collection, Service, etc. Responder/ BlogIndexResponder.php BlogCreateResponder.php html/ index.html.php create.html.php json/ index.json.php read.json.php
<?php
use Framework\Action;
class BlogCreateAction extends Action
{
protected $request;
protected $domain;
protected $responder;
public function __construct(
Request $request,
BlogService $domain,
BlogCreateResponder $responder
) {
$this->request = $request;
$this->domain = $domain;
$this->responder = $responder;
}
?>
<?php
public function __invoke()
{
// is this a POST request?
if ($this->request->isPost()) {
$this->domain->createBlogPost($this->request->getPost());
} else {
// not a POST request, use default values
$blog = $this->domain->getDefault();
}
// set data into the response
$this->responder->setData(array('blog' => $blog));
$this->responder->__invoke();
}
}
<?php
use Framework\Responder;
class BlogCreateResponder extends Responder
{
// $this->response is the actual response object, or a response descriptor
// $this->view is a view or template system
public function __invoke()
{
// is there an ID on the blog instance?
if ($this->data->blog->id) {
// redirect to editing.
$this->response->setRedirect('/blog/edit/{$blog->id}');
} else {
// no, which means it has not been saved yet.
// show the creation form with the current response data.
$this->response->setContent($this->view->render(
'create.html.php',
$this->data
));
}
}
}
https://github.com/pmjones/adr
The biggest value in the factory pattern is that it can encapsulate what would normally be a lot of object setup into a single, simple method call.
<?php
class VehicleFactory
{
public static function build(string $make, string $model, string $color) : VehicleInterface {
$vehicle = new Vehicle;
// vehicle needs a chassis which is produced by another factory
$vehicle->addPart(VehicleChassisFactory::build($make, $model));
// needs an engine built by someone else
$vehicle->addPart(VehicleEngineFactory::build($make, $model));
return $vehicle;
}
}
// build a new white VW Amarok
$myCar = VehicleFactory::build("Volkswagon", "Astra", "white");
$myCar->drive();
<?php
interface VehicleFactoryInterface
{
public function build(VehicleInterface $vehicle) : VehicleInterface;
}
<?php
abstract class VehicleFactory implements VehicleFactoryInterface
{
abstract protected $vehicle;
abstract protected function createEngine(string $make, string $model) : VehicleEngineInterface;
abstract protected function createChassis(string $make, string $model) : VehicleChassisInterface;
public function build(VehicleInterface $vehicle) : VehicleInterface
{
$make = $vehicle->getMake();
$model = $vehicle->getModel();
$vehicle->addPart($this->createEngine($make, $model));
$vehicle->addPart($this->createChassis($make, $model));
return $this->vehicle;
}
}
<?php
class CreateVehiclePage
{
private $vehicleFactory;
public function __construct(TractorVehicleFactory $factory)
{
$this->vehicleFactory = $factory;
}
// or
public function __construct(BoatVehicleFactory $factory)
{
$this->vehicleFactory = $factory;
}
public function build($make, $model)
{
return $this->vehicleFactory->build(new Vehicle($make, $model));
}
}
<?php
class Vehicle
{
public function __construct($make, $model) { .. }
public function buildBoat()
{
$vehicle = new Vehicle($this->make, $this->model);
$factory = new VehicleBoatFactory();
$boat = $factory->build($vehicle);
return $boat;
}
public function buildTractor($make, $model)
{
$vehicle = new Tractor($this->make, $this->model);
$factory = new VehicleTractorFactory();
$tractor = $factory->build($vehicle);
return $tractor;
}
}
immutable objects are simpler to create, test, and use
using them is side-effect free
<?php
class Vehicle implements VehicleInterface
{
private $make;
private $model;
public function __construct(string $make, string $model)
{
$allowedList = [....];
if(!in_array($make, $allowedList)) {
throw new \InvalidArgumentException('This is not a valid vehicle make');
}
$allowedList = [....];
if(!in_array($model, $allowedList)) {
throw new \InvalidArgumentException('This is not a valid vehicle model');
}
$this->make = $make;
$this->model = $model;
}
}
<?php
class Boat extends Vehicle
{
private $make;
private $model;
public function __construct(string $make, string $model)
{
$allowedList = [....];
if(!in_array($make, $allowedList)) {
throw new \InvalidArgumentException('This is not a valid boat make');
}
$allowedList = [....];
if(!in_array($model, $allowedList)) {
throw new \InvalidArgumentException('This is not a valid boat model');
}
$this->make = $make;
$this->model = $model;
}
}
<?php
class VehicleMake
{
private $make;
public function __construct(string $make)
{
$allowedList = [....];
if(!in_array($make, $allowedList)) {
throw new \InvalidArgumentException('This is not a valid vehicle make');
}
$this->make = $make;
}
public function getValue() : string
{
return $this->make;
}
}
<?php
class Vehicle implements VehicleInterface
{
private $make;
private $model;
public function __construct(VehicleMake $make, VehicleModel $model)
{
$this->make = $make;
$this->model = $model;
}
}
$make = new VehicleMake("Mercedes");
$model = new VehicleModel("Benz");
$vehicle = new Vehicle($make, $model);
DTOs do not contain any business logic, they are just hydrated PHP objects with types
They are efficient to properly expose domain data via REST like services to a JavaScript client.
You should not expose your Domain Model as-is over a public interface, such as a REST API.
That is why you should use Data Transfer Objects (DTOs)
You can send DTO’s into battle with the templating layer.
You can ask Doctrine2 to hydrate your DTO's for you
<?php
$query = $em->createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a');
A UUID (Universal Unique Identifier) is a 128-bit number
123e4567-e89b-12d3-a456-426655440000
Created a blocking DB operation
Your object never has a valid ID until persisted
Your object does not work without the DB connected to it providing IDs
You need to persist, then read, then go persist, then read again.
You can generate all this up front and populate your objects and then persist them.
https://github.com/ramsey/uuid
// Generate a version 1 (time-based) UUID object
$uuid1 = Uuid::uuid1();
echo $uuid1->toString() . "\n"; // i.e. e4eaaaf2-d142-11e1-b3e4-080027620cdd
// Generate a version 3 (name-based and hashed with MD5) UUID object
$uuid3 = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net');
echo $uuid3->toString() . "\n"; // i.e. 11a38b9a-b3da-360f-9353-a5a725514269
// Generate a version 4 (random) UUID object
$uuid4 = Uuid::uuid4();
echo $uuid4->toString() . "\n"; // i.e. 25769c6c-d34d-4bfe-ba98-e0ee856f3e7a
// Generate a version 5 (name-based and hashed with SHA1) UUID object
$uuid5 = Uuid::uuid5(Uuid::NAMESPACE_DNS, 'php.net');
echo $uuid5->toString() . "\n"; // i.e. c4a760a8-dbcf-5254-a0d9-6a4474bd1b62
class User
{
public static function create()
{
$this->id = Uuid4();
}
}
class UserImage
{
private $userId;
public function __construct(Uuid $userId)
{
$this->userId = $userId;
}
public function createImage($imagePath)
{
$this->imageStorage->create($userId, $imagePage);
}
}


Master Slave uses 2 or more containers running the same broker; one becomes the master and the other broker(s) the slave(s). If the master dies then a slave takes over being the master.


For more information about the study please don't hesitate to contact the authors of this study: Dr Anne Cori<EMAIL_ADDRESS>or Dr Marc Baguelin<EMAIL_ADDRESS>and please visit the study's website .


{{site.user_description}}
I use HTML5 with Flexbox for designing webpages, Bootstrap 5 for components and Sass to style them nicely.
My Backend stack consists of Python for system level programming, followed by Django for webapps with PostgreSQL as database.
I am proficient with Git, Vim and Amazon Web Services. I have deployed several EC2 instances, with IAM management.


We do not provide javadoc for AccelByte Java SDK at the moment.
Please read README.md instead for now.


Flag
A wrapper representing a Feature Flag / Feature Toggle.
@propertyWrapper public struct Flag<Value>: Decorated, Identifiable where Value: FlagValue
All Flag
s must be initialised with a default value and a description.
The default value is used when none of the sources on the FlagPole
have a value specified for this flag. The description is used for future
developer reference and in Vexlliographer to describe the flag.
The type that you wrap with @Flag
must conform to FlagValue
.
The wrapper returns itself as its projectedValue
property in case
you need to acess any information about the flag itself.
Note that Flag
s are immutable. If you need to mutate this flag use a Snapshot
.
Inheritance
Decorated
, Identifiable
Initializers
init(name:codingKeyStrategy:default:description:)
Initialises a new Flag
with the supplied info.
public init(name: String? = nil, codingKeyStrategy: CodingKeyStrategy = .default, default initialValue: Value, description: FlagInfo)
You must at least provide a default
value and description
of the flag:
@Flag(default: false, description: "This is a test flag. Isn't it nice?")
var myFlag: Bool
Parameters
- name: - name: An optional display name to give the flag. Only visible in flag editors like Vexillographer. Default is to calculate one based on the property name.
- codingKeyStrategy: - codingKeyStrategy: An optional strategy to use when calculating the key name. The default is to use the
FlagPole
s strategy. - default: - default: The default value for this
Flag
should no sources have it set. - description: - description: A description of this flag. Used in flag editors like Vexillographer, and also for future developer context. You can also specify
.hidden
to hide this flag from Vexillographer.
Properties
id
All Flag
s are Identifiable
var id
info
A collection of information about this Flag
, such as its display name and description.
var info: FlagInfo
defaultValue
The default value for this Flag
for when no sources are available, or if no
sources have a value specified for this flag.
var defaultValue: Value
wrappedValue
The Flag
value. This is a calculated property based on the FlagPole
s sources.
var wrappedValue: Value
key
The string-based Key for this Flag
, as calculated during init
. This key is
sent to the FlagValueSource
s.
var key: String
projectedValue
A reference to the Flag
itself is available as a projected value, in case you need
access to the key or other information.
var projectedValue: Flag<Value>
publisher
A Publisher
that provides real-time updates if any time the source
hierarchy changes.
var publisher: AnyPublisher<Value, Never>
This is essentially a filter on the FlagPole
s Publisher.
As your FlagValue
is not Equatable
, this publisher will not
remove duplicates.


Nadine Coyle brands rumours of feud with Cheryl Cole as "fake news"
by Nick FitzgeraldThe former Girls Aloud singer had an open conversation with fellow I'm A Celeb campmates Jacqueline Jossa and Adele Roberts
It's something ITV bosses certainly hoped for when they picked the former Girls Aloud singer to partake in I'm A Celebrity...Get Me Out Of Here.
Nadine Coyle has finally spilled on her relationship with Cheryl Cole. In tonight's show of I'm A Celeb, Nadine sat by the Jungle creek with fellow campmates Jacqueline Jossa and Adele Roberts.
Talk quickly turned to Girls Aloud and it was Jacqueline who asked Coyle what it was like being in a girl band.
Nadine responded by saying:
“Really good, really good, I like being in a girl band. I am one of three sisters and went to an all-girls grammar school so I’m used to being around girls."
Later in the conversation Jaqueline asked the Northern Irish beauty if she got along with everyone in Girls Aloud to which Nadine said "Yes".
Jaqueline then went on to quiz Nadine on her relationship with Cheryl by offering "I’d heard you didn’t get on with Cheryl."
The Derry native shot down the rumours, branding them as "fake news" and said "It wasn't a thing."
Girls Aloud, who rose to fame in 2002, split for good in 2013. It was believed that Nadine and Sarah Harding had a falling out with former bandmates Cheryl, Kimberley Walsh and Nicola Roberts.
It was only recently Kimberley admitted they had "drifted apart" over the years. However, she did say she will be keeping up with I'm A Celeb and wants Nadine to "do well".
Let sleeping dogs lie.


MAX
returns the largest of a selection of data values calculated over a Time dimension.
The GREGORIAN
relations superimpose the Gregorian calendar on the Time dimension. These relations can be useful for calculations on fiscal and nonstandard hierarchies.
NUMBER
MAX (value_expr) OVER (window_clause)
window_clause::=
[ { DIMENSION dimension_id | HIERARCHY hierarchy_id } ] BETWEEN preceding_boundary | following_boundary [WITHIN { PARENT | LEVEL | GREGORIAN {YEAR | QUARTER | MONTH | WEEK} | ANCESTOR AT { DIMENSION LEVEL dim_level_id | HIERARCHY LEVEL hier_level_id } } ]
preceding_boundary::=
{UNBOUNDED PRECEDING | expression PRECEDING} AND { CURRENT MEMBER | expression {PRECEDING | FOLLOWING} | UNBOUNDED FOLLOWING }
following_boundary::=
{CURRENT MEMBER | expression FOLLOWING} AND { expression FOLLOWING | UNBOUNDED FOLLOWING }
A dimensional expression whose values you want to calculate.
The Time dimension over which the values are calculated using the default hierarchy.
The hierarchy over which the values are calculated. If dimension_id
is used instead, the default hierarchy is used.
The name of a level of dimension_id
.
The name of a level of hierarchy_id
.
The preceding_boundary and following_boundary identify a range of time periods within the group identified by the dimension or hierarchy.
UNBOUNDED
starts with the first period or ends with the last period of the group.
CURRENT MEMBER
starts or ends the calculation at the current time period.
A numeric value identifying a period at a particular distance from the current time period that starts or ends the range.
Identifies the range of time periods used in the calculation. Following are descriptions of the keywords.
| Range | Description |
|---|---|
LEVEL |
Calculates all time periods at the same level. (Default) |
PARENT |
Calculates time periods at the same level with the same parent. |
GREGORIAN YEAR |
Calculates time periods within the same Gregorian year. |
GREGORIAN QUARTER |
Calculates time periods within the same Gregorian quarter. |
GREGORIAN MONTH |
Calculates time periods within the same Gregorian month. |
GREGORIAN WEEK |
Calculates time periods within the same Gregorian week. |
ANCESTOR |
Includes time periods at the same level and with the same ancestor at a specified level. |
This example calculates a moving maximum within the calendar year.
MAX(GLOBAL.UNITS_CUBE.UNITS) OVER (DIMENSION GLOBAL.TIME BETWEEN UNBOUNDED PRECEDING AND CURRENT MEMBER WITHIN ANCESTOR AT DIMENSION LEVEL GLOBAL.TIME.CALENDAR_YEAR)
| Time | Units | Maximum |
|---|---|---|
| JAN-06 | 47776 | 47776 |
| FEB-06 | 47695 | 47776 |
| MAR-06 | 51348 | 51348 |
| APR-06 | 47005 | 51348 |
| MAY-06 | 52809 | 52809 |
| JUN-06 | 45419 | 52809 |
| JUL-06 | 48388 | 52809 |
| AUG-06 | 48830 | 52809 |
| SEP-06 | 46354 | 52809 |
| OCT-06 | 47411 | 52809 |
| NOV-06 | 46842 | 52809 |
| DEC-06 | 55052 | 55052 |


nema
is a command line generator that target full stack:
It generates API/Templates from Swagger 2.0 YAMLS.
Frontend
Backend
nema
Command line Help _ _ _ _ _
| |(/_| | |(_|1.0.0
Usage: nema [options]
Code generation from swagger
Options:
-V, --version output the version number
--angular5-api TARGET(full project): Generate an Angular 5 Module Api client
--mongoose TARGET(plugin@express): Generate Mongoose Schema, Models & Repositories
--express TARGET(full project): Generate Express app/routes
--angular5-form-template <path> TARGET(plugin@angular5-api): Generate an Angular 5 Template from given model
--override-models Override all models while agreggating
--override-methods Override all methods while agreggating
--lint Lint output (tslint), this may take a while
--swagger <path> Path to swagger yml, repeat to aggregate (default: )
--file <path> Output path for TARGET(file) path
--dst <path> Output path for TARGET(project), default: same as the first swagger
-h, --help output usage information
At least one swagger file is required
At least one TARGET is required
Examples:
nema --swagger=swagger-file.yml --mongoose --express --dst server/
nema --swagger=swagger-file.yml --angular5-api --dst angular/app/src/api/
You can aggregate many Swaggers into one unique generation.
nema
will take global schema configuration from the first file and
add parameters, definitions and paths from each other files.
In the end you will have one unique module with all methods an models.
Be aware of collisions :)
nema --swagger=./base-api.yml --swagger=./products-api.yml --angular5-api
nema
has to do some triage, we cannot support all SWAGGER features and also
can't do everything 100% standard
.
Every type
with type:object
must be declared at definitions (first level).
everything in nema
need a name
Operation Object: operationId
is required
schemes
is required
Do not support $ref
to external source files
/swagger
path is forbidden it's used by swagger-ui
A sucess Response (2xx) must be defined and only one
default
response is considered as 200
No recursive types
It will give you compile errors on generated code:
error TS2395: Individual declarations in merged declaration 'XXX' must be all exported or all local.
error TS2440: Import declaration conflicts with local declaration of 'XXX'.
type:string
with format: date|date-format
are treated the same:
Javascript Date
type:number
with format: int32|int64|float|double
are the same:
Javascript Number (double)
Things that may change in the future:
nema
generated files are meant to be committed. And inside some files you
can even work. Like express routes.
Zoned templates are generated files that are safe to edit by you (our beloved end-user). Zones are delimited with an HTML like comment.
For example:
...
export const app = express();
//<express-configuration>
app.set("mongodb", process.env.MONGO_URI || "mongodb://<IP_ADDRESS>:27017/test");
// false to disable
app.set("cors", false);
//</express-configuration>
...
Internal zones are marked as <internal-*>
and should not be edited. This is
used to compose generated files.
If you dont add properties to and object type, will be any in TypeScript.
definitions:
object_with_any:
type: object
properties:
this_is_any:
type: object
nema
(custom) metadatax-nema:
angularClientModuleName: XXX
angularClientNodeModuleName: xxx
apiName: XXXApi
frontBasePath: /reverse-proxy/api/v1 # optional
Create an angular 5 resolve see example below
Override endpoint properties, this allow to use other generators without collisions or aggregate multiple files renaming operationIds...
basePath: /books
paths:
/{productId}:
get:
description: get book product
operationId: getProduct
x-override-front:
operationId: getBook
The final operation id will be: getBook dev note: getProduct won't be accesible at any target generation.
Some parameter could be injected by a reverse proxy / microgateway, those are useful for backend, but you don't want those in your front application.
paths:
/{productId}:
get:
description: get book product
operationId: getProduct
produces:
- application/json
parameters:
- name: reverse-proxy-ip
x-nema-auto-injected: true
in: header
description: BBVA user code.
required: true
type: string
Set plural used for generating, but default will use pluralize
Mark model as a db entity (mongoose treat it as a collection)
definitions:
User:
x-nema-db: true
type: object
required:
- userlogin
- password
properties:
userlogin:
type: string
description: Userlogin
maxLength: 64
x-nema-lowercase: true
x-nema-unique: true
password:
type: string
description: Userlogin
maxLength: 64
x-nema-lowercase: true
x-nema-unique: true
Force a custom control when generating form templates.
for example: type: string
will be an input text, if you want a textare use:
x-nema-control: textarea
Mark type as "cannot-be-created/updated".
In forms is displayed as disabled.
When you do the API implementation you should handle it manually. <!--
Force lowercase
Mark the property as unique. -->
Tell nema your type is a foreignKey (mongoose treat it as a ref)
definitions:
Test:
type: object
properties:
subscribers_user_ids:
type: array
description: Usuarios inscritos
items:
type: string
x-nema-fk: "#/definitions/User"
nema
create a Resolve for Angular and search parameters in parents routes:
params
(route.snapshot.params
) & data
(route.snapshot.data
).
params
has higher priority than data
.
Angular route configuration:
{
path: "strategy/:strategyId",
component: RootComponent,
data: {},
resolve: {
strategy: StrategyResolve,
}
}
Swagger extension:
paths:
/strategy/{strategyId}
parameters:
- name: strategyId
in: path
description: Strategy identifier
required: true
type: string
get:
name: getStrategy
description: Get a single strategy by Id
x-nema-resolve:
name: StrategyResolve
errorURL: /error
parameters: # map route.snapshot.params with the method parameter name
strategyId: strategyId
Angular route configuration:
{
data: {
ref2Id: 6
},
children: [
{
path: "App1/files/:fileId",
component: GetFilesComponent,
data: {
appName: "App1"
},
resolve: {
strategy: FileResolve, // id -> fileId: ?, app -> appName: "App", refId -> ref2Id: 6
}
},
]
}
{
path: "App2/files/:fileId",
component: GetFilesComponent,
data: {
appName: "App2",
refId: 7
},
resolve: {
strategy: MagicResolve, // id -> fileId: ?, app -> appName: "App2", refId -> refId: 7
}
}
Swagger extension:
paths:
/strategy/{id}
parameters:
- name: id
in: path
description: identifier
required: true
type: string
- name: app
in: path
description: Application name
required: true
type: string
- name: refId
in: path
description: Reference Id, depends on your application
required: true
type: string
get:
name: getFiles
description: Give me some sparks
x-nema-resolve:
name: FileResolve
errorURL: /error
parameters:
id: fileId
app: appName
refId: # search any, the first found is used
- refId
- ref2Id
It's recommended to use a global component, so you don't need to handle subscriptions.
import { RestApi } from "./api";
import { Component } from "@angular/core";
import { Subscription } from "rxjs/Subscription";
@Component({
templateUrl: "./PlanDetails.component.html",
})
class TestComponent implements OnDestroy {
subscription: Subscription;
constructor(
public restApi: RestApi,
) {
this.subscription = this.restApi.onError.subscribe((err: CommonException) => {
// guard: only once!
// this may not be needed... if you have a global component
if ((err as any).handled !== true) {
(err as any).handled = true;
//display the error!
console.log(err.message);
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
import { RestApi } from "./api";
import { Component } from "@angular/core";
import { Subscription } from "rxjs/Subscription";
@Component({
templateUrl: "./PlanDetails.component.html",
})
class TestComponent implements OnDestroy {
testId: number;
constructor(
public restApi: RestApi,
) {
}
test() {
const x = this.restApi.test(
this.testId,
{ emitError: false } // handle error locally
);
x.subscribe((response) => {
// sucess
}, (err: api.CommonException) => {
// error
});
}
}
Notes to develop. Not meant to anybody of you :)
While developing rebuild is necessary everytime, edit bin/nema.js
and
uncomment the compilation step,
then remove from working copy so it won't be committed
git update-index --assume-unchanged bin/nema.js
# Install mongodb
# run server
"C:\Program Files\MongoDB\Server\3.6\bin\mongod.exe" --dbpath C:\data\db
Generated using TypeDoc


Message: {{message}}
{% if message[:4] == '502 ' %}If the SSL certificate of iotsa device "{{device}}" is not trusted by this Igor please try to connect using the form at the bottom of the iotsa device list page and select the Do not check SSL certificates option.
{% elif message[:4] == '401 ' %}To allow access to module "{{module}}" iotsa device "{{device}}" requires either a trusted capability (which Igor does not have yet) or username/passord credentials. You can use the latter by selecting this device on the form at the bottom of iotsa device list and providing them in the credentials field.
{% endif %} {% endif %} {% if noverify %}You are accessing {{device}} with SSL (https) certificate verification disabled.
If this is a new iotsa device that is still using the factory-installed default certificate you can install an Igor-signed certificate.
{% if status.currentMode == 1 %}Install Igor-signed certificate to {{device}}
Alternatively, you can install a private key and certificate obtained through other means by visiting the device directly (without Igor intervention) by visiting {{protocol}}://{{device}}:{{port}}/config.
Or you can paste the private key and certificate (as base64-encoded DER files) in the fields below:
{% else %}To do this you must first set the iotsa device in configuration mode, below.
{% endif %} {% endif %}Device {{device}} is operating in normal mode (in other words, you cannot change important settings or reprogram it).
{% endif %} {% if status.requestedMode %}You have requested a mode change, but not rebooted {{device}} yet. Please do so within {{status.requestedModeTimeout}} seconds and select refresh to reload this page.
{% endif %} {% if not status.currentMode %}To change device settings you have to request configuration mode here, and then power-cycle the device to demonstrate you have physical access (in other words: to show that you actually own the device and it is somewhere in your home, and that you are not a hacker who managed to get access to the local wifi network).
After power-cycling the device will be configurable for a few minutes (otherwise it will revert to normal operating mode). After submitting the request you may have to refresh this page after the device has rebooted.
{% elif status.currentMode == 1 %}The device is in configuration mode (it will revert to normal mode in {{status.currentModeTimeout}} seconds). Use the following form to set values.
{% elif status.currentMode == 2 %}The device is in OTA mode and can be reprogrammed over the air. The Igor iotsaDiscovery plugin has no support for this yet, use the iotsaControl command-line tool to reprogram the device.
{% else %}Unknown device mode {{status.currentMode}}
{% endif %}| Key | Value |
|---|---|
| {{k}} | {{v}} |
Select the following links to get status information for specific modules on {{device}} and possibly modify it:
After retrieving the status it will be stored in /data/devices/{{pluginName}}/{{device}} where you can inspect it.
You can also modify the data for a module there, in the Igor database, and then upload it to the device with the following form:


Home
Supply
Woods
Hardware&Doors
Plumbing&Sanitary
Cements
Gallery
Contact us
Contact us
Do Visit us
Contact Us
Near Railway Station,Koregaon
415501
Phone no +919822830245
<EMAIL_ADDRESS>Send Message


{% extends 'base.html' %} {% block content %} {% include 'base_jumbotron.html' %}
Perform visual field examinations using your smartphone and a virtual reality (VR) headset.
Learn moreUse perceptual learning and simple repetitive exercises to improve (or even recover) your visual field.
Learn moreThe smartphone app as well as the server are freely available as open source software on GitHub.
Learn morePerform continuous home monitoring of your visual field.
Measure equidistantly-sampled visual fields (left image) or Octopus G1-based visual fields (right image).
Smartphone, virtual reality (VR) headset, and bluetooth input device required.
Online storage and evaluation of results.
Recover visual field defects as shown in, for example, these studies:
Mueller, Mast and Sabel. Recovery of visual field defects: A large clinical observational study using vision restoration therapy, Restorative Neurology and Neuroscience 25(5-6), pp. 563–572, 2007.
Sabel and Gudlin. Vision Restoration Training for Glaucoma - A Randomized Clinical Trial, JAMA Ophthalmologl 132(4), pp. 381-389, 2014.
The smartphone app as well as the server are freely available as open source software on GitHub (after publication of the complementary research article).
The smartphone app is implemented using Unreal Engine 4 (UE4), which facilitates exporting the app for all major smartphone operating systems.
Login screen to upload and store visual field assessments on the VFAT server.
Program selection to start a visual field assessment or calibrate brightness.


ppmtolj(1) ppmtolj(1) NAME ppmtolj - convert a portable pixmap to an HP LaserJet PCL 5 Color file SYNOPSIS ppmtolj [-gamma val] [-resolution 75|100|150|300|600] [-delta] [-float] [-noreset] [ppmfile] DESCRIPTION Reads a portable pixmap as input and converts it into a color file suit‐ able to be printed by an HP color PCL 5 printer. OPTIONS -delta Apply delta row compression to reduce the size of the pcl file. -gamma int Gamma correct the image using the integet parameter as a gamma (default 0). -float Suppresses positioning information. The default is to write the sequence ESC&l0E to the output. -noreset Prevents writing of the reset sequence to the begining and end of the output. -resolution Set the required output resolution 75|100|150|300|600 REFERENCES HP PCL 5 & Color Reference Guide BUGS None known. AUTHOR Copyright (C) 2000 by Jonathan<EMAIL_ADDRESS>4 Sept 2000 ppmtolj(1)


How does life look through the pleasure, passion and purpose lens
I found this very interesting. Pleasure for me has manifested itself in a big way throughout my life, be it through drinking when I was younger to spending lots of money on material items. I have been aware for a while that this is the case but the chapter in search inside yourself put some context around it. These short term pleasures have invariably left me feeling bad and low afterwards and the initial euphoria soon wears off.
The passion stage was something I found when I was woodworking. When I hit that sweet spot nothing could touch me and I would be steaming along. However quite often something would come along and slow the momentum. I found myself buzzing and thinking about it when I wanted to sleep, however the lows when things weren't working could be quite bad.
Working to a higher purpose is something I have thought about a lot. I believe strongly in equality and social justice but my actions don't match my thoughts. I would like to find a job or a hobby where I made a tangeable difference to peoples lives, not just signing online petitions and ignoring the tough stuff. I am working towards a transition from pleasure to purpose and trying to live mindfully and care about what I buy and who I support. Interstingly just writing this was really easy as it's something that has been on my mind.
My core values
Love, honesty, compassion, respect and standing up for what is right
Resilience
I found the whole resilience exercise very interesting. It know from experience that it is very easy to be elated with wins and crushed with losses. I found the mindfulness very helpful in recognising that this is something I do. By letting good and bad come and go without grasping at them there would not be such highs and such lows and we would be more resiliant to failure. This will have to tie in with the idea of doing something with purpose rather than pleasure.


Collins bill to combat Lyme and other tick diseases moves on
BANGOR, Maine (AP) - A U.S. Senate committee is advancing a proposal from Sen. Susan Collins to improve research about Lyme disease and other tick-borne infections.
Collins, a Republican, introduced the proposal with Democratic Minnesota Sen. Tina Smith. It’s also designed to beef up prevention, diagnostics and treatment for tick-borne diseases, and it’s headed to the full Senate next.
The proposal’s named the Kay Hagan Tick Act in honor of former Sen. Kay Hagan of North Carolina who died in October of complications from Powassan virus, a tick-borne infection.
Cases of Lyme disease nearly doubled in Maine from 2010 to 2018. Collins describes the surge of tick-borne diseases as a “burgeoning public health crisis.”
The proposal would require the U.S. Department of Health and Human Services to develop a national strategy about the diseases.
Sign up for Daily Newsletters
Copyright © 2019 The Washington Times, LLC.
Please read our comment policy before commenting.


Class SimplifiedGazeDataEventArgs
EventArgs for OnGazeData
Inheritance
Inherited Members
Namespace: SimplifiedEyeTracker
Assembly: SimplifiedEyeTracker.dll
Syntax
public sealed class SimplifiedGazeDataEventArgs : EventArgs
Fields
| Improve this Doc View SourceDeviceTimeStamp
Device Time Stamp.
Declaration
public long DeviceTimeStamp
Field Value
| Type | Description |
|---|---|
| System.Int64 |
IsLeftValid
If the Left eye is closed or couldn't get valid data, it becomes false.
Declaration
public bool IsLeftValid
Field Value
| Type | Description |
|---|---|
| System.Boolean |
IsRightValid
If the Right eye is closed or couldn't get valid data, it becomes false.
Declaration
public bool IsRightValid
Field Value
| Type | Description |
|---|---|
| System.Boolean |
LeftEyeMovementType
[Left Eye] Movement Type (Saccade, Not A Saccade, Fixation, Unknown)
Declaration
public EyeMovementType LeftEyeMovementType
Field Value
| Type | Description |
|---|---|
| EyeMovementType |
LeftGazeAngularVelocity
Angular Velocity for Left Gaze in deg/s
Declaration
public double LeftGazeAngularVelocity
Field Value
| Type | Description |
|---|---|
| System.Double |
LeftX
X Coordinate of the Left eye gaze in the user display area.
0.0
is the left edge, 1.0
or screenWidth
is the right edge of the screen.
Declaration
public double LeftX
Field Value
| Type | Description |
|---|---|
| System.Double |
LeftY
Y Coordinate of the Left eye gaze in the user display area.
0.0
is the top edge, 1.0
or screenHeight
is the bottom edge of the screen.
Declaration
public double LeftY
Field Value
| Type | Description |
|---|---|
| System.Double |
RightEyeMovementType
[Left Eye] Movement Type (Saccade, Not A Saccade, Fixation, Unknown)
Declaration
public EyeMovementType RightEyeMovementType
Field Value
| Type | Description |
|---|---|
| EyeMovementType |
RightGazeAngularVelocity
Angular Velocity for Right Gaze in deg/s
Declaration
public double RightGazeAngularVelocity
Field Value
| Type | Description |
|---|---|
| System.Double |
RightX
X Coordinate of the Right eye gaze in the user display area.
0.0
is the left edge, 1.0
or screenWidth
is the right edge of the screen.
Declaration
public double RightX
Field Value
| Type | Description |
|---|---|
| System.Double |
RightY
Y Coordinate of the Right eye gaze in the user display area.
0.0
is the top edge, 1.0
or screenHeight
is the bottom edge of the screen.
Declaration
public double RightY
Field Value
| Type | Description |
|---|---|
| System.Double |
SystemTimeStamp
System Time Stamp.
Declaration
public long SystemTimeStamp
Field Value
| Type | Description |
|---|---|
| System.Int64 |
SystemTimeStampInterval
Interval between the previous system time stamp and the latest system time stamp
Declaration
public int SystemTimeStampInterval
Field Value
| Type | Description |
|---|---|
| System.Int32 |


Home
Works
Repositories
Contact
Just me wandering around...
"I don't really know where I am going until I turn around and look back. Then I still don't know but I realize how far I went."
- Random -
Photoshop Collection
Visit
GitHub
Java
Python
Be nice and email me your interests.
Send


--- title: "Comparing R, Python, and Julia for a simple data-wrangling task" author: João Pedro S. Macalós slug: r-python-julia-wrangling categories: '' tags: [data-wrangling] subtitle: '' summary: '' authors: [] lastmod: '2021-06-15' featured: true math: true image: placement: 2 focal_point: 'Center' preview_only: true ---
The objective of this notebook is to compare how R-dplyr, Pandas, and Julia DataFrames handle a very common and simple data-wrangling task: load a CSV file in memory, correct data types, filter out the top 3 rows, exclude the missing values and then plot the resulting values.
I had the idea to make this post when I downloaded the dataset containing the monthly evolution of commodity prices this week. To give a bit of context, there’s a debate in the economics community about a new new commodities supercycle. Since this topic is close to the research subject of my PhD, I decided to get the data from the source and plot it myself.
When I opened the database, I realized that the excel file was “dirty” enough to require some data-wrangling, but simple enough to do it in a couple of lines. Therefore, a perfect example for a short comparison between R, Python, and Julia.
The original dataset can be obtained directly at the IMF’s website.
# Load required libraries
library(tidyverse)
library(lubridate)
# Read csv
commodities <- read_csv('../../../Datasets/imf-commodities.csv')
# Data-wrangling
commodities <- commodities %>%
select(date = Commodity, comm = PALLFNF) %>%
slice(4:n()) %>%
drop_na() %>%
mutate(
date = ym(date),
comm = as.numeric(comm)
)
head(commodities)
## # A tibble: 6 x 2
## date comm
## <date> <dbl>
## 1 1992-01-01 50.3
## 2 1992-02-01 50.2
## 3 1992-03-01 50.3
## 4 1992-04-01 50.7
## 5 1992-05-01 52.1
## 6 1992-06-01 52.3
# Plot
commodities %>%
ggplot(aes(x=date, y=comm)) +
geom_line(aes(color='All commodity prices (IMF)')) +
theme(legend.position = c(.8, .1),
legend.title = element_blank()) +
labs(x="", y="") +
scale_color_manual(values="black")
reticulate::use_condaenv("job-scrapper")
# Load required libraries
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# Read csv
commodities = pd.read_csv('../../../Datasets/imf-commodities.csv')
# Data wrangling
commodities = (
commodities
.loc[3:, ['Commodity', 'PALLFNF']]
.dropna()
.assign(
date=lambda x: pd.to_datetime(x.Commodity, format='%YM%m'),
comm=lambda x: x.PALLFNF.astype('float')
)
)
commodities.head()
## Commodity PALLFNF date comm
## 147 1992M1 50.254 1992-01-01 50.254
## 148 1992M2 50.247 1992-02-01 50.247
## 149 1992M3 50.273 1992-03-01 50.273
## 150 1992M4 50.689 1992-04-01 50.689
## 151 1992M5 52.135 1992-05-01 52.135
plt.close()
# Plot
sns.lineplot(
data=commodities,
x='date', y='comm',
label='All commodity prices (IMF)'
);
plt.legend(loc="lower right")
## <matplotlib.legend.Legend object at 0x7f2f514a9430>
plt.show()
# Load required packages
using CSV
using DataFrames
using Plots
using Pipe
using Dates
# Read csv
commodities = CSV.read("../../../Datasets/imf-commodities.csv", DataFrame);
# Data-wrangling
commodities = @pipe commodities |>
_[4:end, [:Commodity, :PALLFNF]] |>
dropmissing(_) |>
transform(_, :Commodity => (x -> replace.(x, ("M" => "-"))) => :date) |>
transform(_, :date => (x -> Date.(x, "y-m")) => :date) |>
transform(_, :PALLFNF => (x -> parse.(Float32, x)) => :comm);
first(commodities, 6)
## 6×4 DataFrame
## Row │ Commodity PALLFNF date comm
## │ String String Date Float32
## ─────┼─────────────────────────────────────────
## 1 │ 1992M1 50.254 1992-01-01 50.254
## 2 │ 1992M2 50.247 1992-02-01 50.247
## 3 │ 1992M3 50.273 1992-03-01 50.273
## 4 │ 1992M4 50.689 1992-04-01 50.689
## 5 │ 1992M5 52.135 1992-05-01 52.135
## 6 │ 1992M6 52.347 1992-06-01 52.347
# Plot
Plots.plot(
commodities.date,
commodities.comm,
html_output_format=:png, # Important for nice printing
label = "All commodity prices (IMF)",
legend= :bottomright
)
One of the main complaints about Julia was the annoying time to first plot. Although there is still a delay to run the first plot in Julia, version 1.6. greatly improved on this aspect, and the difference nowadays is much much smaller.
All three languages can perfectly handle such a small data-wrangling task.
However, I think that it is clear that the tidyverse
packages provide the highest abstraction with their efficient data masks. Therefore, it ranks as the easiest code to read for someone that is not used to code.
Pandas
comes in a close second, but lambda
functions require some (little) practice to get used to.
Julia DataFrames
comes in third as it requires placeholders (_
) in every line, macros, lambda functions, broadcasting. As a consequence, the code is cluttered with symbols (@
, _
, .
, :
, ->
, =>
). In any case, it is nothing particularly complicated and anyone can get used to it with a little practice.
Plotting-wise, I think that the three alternatives that I explored in the post have their pros and cons. Julia Plots
seems quite intuitive, but there are still some bugs like the size of the Plot display in HTML format that requires a lot of googling to partially get rid of.
ggplot2
, on the other hand, requires some practice to get used to. Nonetheless, it is worth it as it is just amazing how flexible it is, and how wide the community is. There’s a very high chance that any plot you want to make was already done using ggplot2
.
Finally, Seaborn
is a great improvement over matplotlib.pyplot
, and I see it becoming a serious contender to gggplot2
hegemony. For me, the main problem of Seaborn
is that whenever you need to customize it, you are left in the wild kingdom of pyplot
and its overly complicated syntax.
My conclusion is that all three languages are amazing. I love R, and I must admit that the tidyverse
packages are the main responsible for it. Python
is impressive for its versatility, and a must nowadays if you want to work in the industry. Finally, I want to love Julia, but I think it is not quite there yet. It is supposed to be fast as C and as readable as Python – and I love this idea. However, the community remains quite small, which increases substantially the entry cost as it takes much longer to get fluent with it, and it is rarely used in the industry.
PS: I can’t finish without praising knitr
and RMarkdown
notebooks. It’s incredible that I ran all this post in a single notebook in Rstudio. It would even be possible to use the variables defined in one of the languages in the others.


Ingredients
- 400g (3-4 pieces) hot smoked salmon - no skin
- 200g asparagus tips
- 500g baby potatoes
- 200g mixed salad leaves
- 140g radishes
- 30g fresh mint/basil/parsley
- 4 spring onions
- 2 lemons (juiced)
- 6tbsp olive oil
- chili flakes/fresh chillies (1tbsp/2 chillies - less if salmon is already seasoned with chili)
- salt & pepper
Steps
- 1. Boil potatoes in salted water for 10 mins until tender, adding the asparagus tips for the final 2 mins of cooking (or steam afterwords). Drain and allow to cool. Whisk together the salad dressing ingredients. then season to taste.
- 2. In a large bowl, toss together the potatoes, asparagus, salad leaves, herbs and radishes. Add two-thirds of the dressing, thoroughly mix through the salad, then spread the salad over a large platter. Break the hot-smoked salmon into large chunks, then scatter over the top along with the spring onions. Finish by pouring remaining dressing over the top.


Preparation time
less than 30 mins
Cooking time
10 to 30 mins
Serves
Serves 4
Lobster curry is a beautiful dish, the combination of succulent lobster with vibrant spices and coconut milk is spot on.
For the Thai red curry paste, place all the ingredients, including the soaking water, into a pestle and mortar, or food processor, and blend to a fine paste.
For the lobster curry, heat a wok or frying pan until hot, add three tablespoons of the curry paste and cook until just starting to change colour then add the coconut milk.
Bring to a simmer and cook for five minutes then add the fish sauce, tamarind, lime and sugar. Check the seasoning and add salt and freshly ground black pepper as necessary.
Carefully remove the meat from the cooked lobsters, reserving the shells, and place the meat into the curry sauce and cook over a low heat until hot through.
Add the coriander and stir through, then spoon the lobster meat back into the shells.
For the pad Thai, heat a wok until hot, add the oil, shallot, chilli, garlic and ginger and stir fry for a minute.
Add the prawns and cook for another minute.
Add the noodles and bean sprouts and stir fry to heat through. Then add the tamarind paste, fish sauce, soy sauce and lime juice and stir to coat everything evenly.
Cook for 1-2 minutes, until hot, then add the chopped coriander.
To serve, pile pad Thai onto each serving plate and sprinkle with crushed peanuts.
Place the lobster alongside the pad Thai and spoon over the curry sauce to finish.


Hey, I'm Deziree!
Biography
Greetings! My name is Deziree Teague and I was born and raised in Seattle, Washington. I recently moved back to the Pacific Northwest after spending 5 years abroad. I am thrilled to be studying software devlopment at Code Fellows and I look forward to transitioning my career into tech!
Outside of work, I love to spend time outdoors. These are a few cool activities I have experienced over the years:
- zip-lining
- white-water rafting
- hiking Mount Fuji in Japan
- repelling off a cliff in Costa Rica
- scuba diving at the Great Barrier Reef
- stand up paddle boarding on Lake Washington
Education
I graduated from the University of Washington in 2011 with a bachelor's degree in Communication and a minor in Diversity. During my time there, I had the opportunity to study abroad which fueled my love for travel! My first study abroad trip was to Buenos Aires, Argentina in 2010. I also studied in the northeastern state of Bahia, Brazil in the spring of 2011.
Work & Travel Experience
In 2013, I moved to Heredia, Costa Rica to complete my certification in Teaching English as a Foreign Language (TEFL). Since then, I have taught English to students ranging from preschoolers to retired adults! Teaching allowed me to live and work in Costa Rica, Guatemala, Spain, and Australia. These experiences taught me resourcefulness, adaptability, and interpersonal communication.
My Top 10 International Travel Experiences (in no particular order):
- Greece
- Brazil
- India
- Spain
- Morrocco
- Argentina
- Thailand
- Australia
- Costa Rica
- Czech Republic
Goals
Upon graduation from Code Fellows, I hope to start my career as a full-stack developer.


---
layout: page
title: "Practical Vim (for Kathryn Amaral)"
prev: None
next: f_0001.html
book_path: books/drew-neil-practical-vim-edit-text-at-the-speed-of-thought-_oeb/
---
{% include JB/setup %}
{% raw %}
Practical Vim
Edit Text at the Speed of Thought
by Drew Neil
Version: P1.0 (September 2012)
Copyright © 2012 The Pragmatic Bookshelf. This book is licensed to
the individual who purchased it. We don't copy-protect it
because that would limit your ability to use it for your
own purposes. Please don't break this trust—you can use
this across all of your devices but please do not share this copy
with other members of your team, with friends, or via file sharing services. Thanks.
—Dave & Andy.
{% endraw %}


BREAKING Germany mine collapse: Up to 30 workers trapped underground after explosion
A major rescue operation is underway after the explosion left about 30 workers trapped - including two who are injured - at the Teutschenthal facility, near the town of Halle, Germany
by Chris Kitching, https://www.mirror.co.uk/authors/chris-kitching/About 30 workers are trapped in a coal mine following an explosion.
Two people have been injured in the blast at the Teutschenthal facility, near the town of Halle in eastern Germany.
The trapped workers are believed to be in a safety area underground.
A major rescue operation is underway.
Halle is about 95 miles south-west of Berlin.
We'll be bringing you the very latest updates, pictures and video on this breaking news story.
Please check back regularly for updates on this developing story here at Mirror.co.uk.
For the latest news and breaking news visit Mirror.co.uk/news.
Get all the big headlines, pictures, analysis, opinion and video on the stories that matter to you.
Follow us on Twitter @DailyMirror - the official Daily Mirror & Mirror Online Twitter account - real news in real time.
We're also on Facebook /dailymirror - your must-see news, features, videos and pictures throughout the day from the Daily Mirror, Sunday Mirror and Mirror Online.


Hi [NAME],
I am so grateful to the community of friends we have been blessed with. A special thank you to each and every one of you who have done so much to support us this past month. We have friends sharing the documentary The Reality of Truth on YouTube (see the film here), providing ratings and reviews on Google Maps (see reviews here) and TripAdvisor (see reviews here), podcast interviews, health and wellness articles for the press, video testimonials, refer-a-friend and word of mouth. Thank you for helping us by sharing your enthusiasm with your networks of like-minded friends and family.
For a complete list of speakers and dates, please call +1<PHONE_NUMBER>.
Michael Beckwith
Aug 1-8
Michael Beckwith
Aug 1-8
How was your Rythmia experience? We’d like to hear about it! Our 2nd Quarter contest is open to guests who checked out between April 1 - June 30 The winner will receive an all-inclusive 7-night stay at the resort. So please create your video while your experience is fresh in your mind. You can submit your video any time between now and July 11. Drawing July 13 and announcement via social media July 18, 2017.
Record a :30 - 2 minute video of YOUR RYTHMIA STORY
Post video to your social media (Facebook, Instagram, Twitter) and include the hashtag: #MyRythmiaStory
Email your video to<EMAIL_ADDRESS>Include your name and phone number to be automatically entered for a chance to WIN a 7 night stay at Rythmia (does not include airfare).
Please do not use copyright materials in your submission (e.g. photos or music you do not have permission to use).
For more information or to book your next trip please call us at<PHONE_NUMBER> or visit our website. Pricing starts at $299* per night.
If you're looking for your soul's purpose, please join us and come get your Miracle!
Love,
Gerry
*Pricing does not include resort surcharge, pricing is per night per person.


# setting up the problem
library(tibble)
library(dplyr)
library(ggplot2)
library(glue)
= 50
num_obs set.seed(1234)
<- tibble(x = runif(num_obs, -10, 10), y = runif(num_obs, -10, 10))
df
# Step 1: choose number of centroids
= 3
k
set.seed(441)
# step 2: assign randomly each point to a cluster
<- df |> mutate(centroid = sample(1:k, n(), replace = TRUE)) df
The purpose of this article is to get a deeper dive into Kmeans as an unsupervised machine learning algorithms. To see the algorithm at work on some financial data, you can use the post on kmeans and regime change.
As mentioned, Kmeans is an unsupervised learning algorithm, aiming to group “observations” based on their distances to a fixed number of “centroids” (aka: the fixed number is K). Each centroids is defined as the mean (in each dimension) of all the points belonging to that centroid. All the points belonging to a centroid makes a cluster: all the observations belonging to the k-centroid makes the k-cluster.
The objective is, for a given number of centroids (i.e. k), to minimize the total within-cluster variation or intra cluster variation (distance from the observation to the centroid).
The standard Kmeans algorithm aims to minimize the total sum of the square distances (Euclidean distance) between observations and centroids.
First, we calculate the within-centroid sum of square: \[W(C_k) = \sum_{x_i \in C_k} (x_i - \mu_k)^2 \tag{1}\]
- \(x_i\) is the ith-observation in our dataset
- \(k\) is the number of centroids and \(C_k\) is the \(k^{th}\) centroid.
- \(\mu_k\) is the mean value of all the points assigned to the \(C_k\) cluster. You get the mean of the centroid is a p-dimensional vector comprising the mean of each of the variables.
The objective is to minimize the total within cluster variation, that is the total sum of the distance of each observations to its centroid and that for each of the k-centroids: \[tot.withinss = \sum_{k=1}^k W(C_k) = \sum_{k=1}^k \sum_{x_i \in C_k} (x_i - \mu_k)^2 \tag{2}\]
The Kmeans algorithms
Although there are 3 different ways to achieve the objective function, we’ll only explain the Hartingan-Wonk algorithm (1979).
It is noted that none of the algorithms guarantees a global minima. They all can be stuck into a local minima.
- Step 1 Choose the number of centroids
- Step 2: Cluster assignment step All observations are randomly assigned a cluster (the first k centroids). Another way to start is to randomly pick k observations that will be used as first centroids in the given hyperspace.
- Step 3: Calculate the centroid location Find the centroid location by calculating the mean value for each of the variables.
- Step 4: Find distance to each centroids Find the distance between each observation and each centroid. Assign the centroid with minimum distance to that observation.
- Step 5: Centroids update Recalculate the centroid location if there was a change of centroid mean. In other words: calculate a new mean for each centroids using all the \(x_i \in C_k\).
- step 6: Reaching convergence Repeat step 4 and 5. Once the new mean is established, we calculate again, for each observations its closest centroid. Then calculate again a new mean. We reiterate this step this until each given centroids are not changing anymore (or the change is below a given threshold).
Because of the initial random allocation of points to a cluster, results might differ. This is why in the native R kmeans() you can specify the nstart parameter and only the allocation providing the minimum distance will be kept.
Kmean - Hartingan-Wonk in practice.
We are going to define a couple of function we will use more than once.
<- function(df) {
calculate_centroid_mean <- df |> group_by(centroid) |>
yo summarize(mean_x = mean(x), mean_y = mean(y))
#print(yo)
return(yo)
}
<- function(df) {
total_within_cluster_distance <- df |>
yo mutate(distance = (x - centroid_loc$mean_x[centroid])^2 +
- centroid_loc$mean_y[centroid])^2)
(y return(sum(yo$distance))
}
# need to initialize an empty vector for the distance of the observation to a centroid
<- c() dist_centroid
# Starting the iteration process
# step3:
## a: calculate mean of each centroids
<- calculate_centroid_mean(df)
centroid_loc
## b: calculate sum of distance between each observation and its assigned cluster
print(glue('Initial sum of within-cluster distance is: ',
round(total_within_cluster_distance(df), 2)))
Initial sum of within-cluster distance is: 3014.94
= 1 # to keep track on how many round / loops we are doing
rd = 0 # to keep track on how many observations have not changed their centroids
i
# we shall be running the loop until we have no more change of centroids
while (i < num_obs) {
= 0 # we keep going with the process until no more change of centroids for all the observations
i
# Step 4: for each data point
for (obs in 1:num_obs) {
# for each centroid
for (centroid in 1:k) {
# find distance from the observation to the centroid
= sqrt((df$x[obs] - centroid_loc$mean_x[centroid])^2 +
dist_centroid[centroid] $y[obs] - centroid_loc$mean_y[centroid])^2)
(df# print(glue(' The distance from point ', obs, ' to centroid ', centroid, ' is ', round(dist_centroid[centroid], 2)))
}
# assign the observation to its new centroid (based on min distance)
= df$centroid[obs]
prev_centroid = which.min(dist_centroid)
post_centroid $centroid[obs] = post_centroid #assign the new centroid
df
if (prev_centroid != post_centroid) {
# we recaluate the centroid
<- calculate_centroid_mean(df)
centroid_loc print(glue(' The initial centroid for point ', obs, ' was ',
'. It is now ', post_centroid))
prev_centroid, # print(centroid_loc)
else {
} = i + 1
i #print(' No change in centroid')
}
}= rd + 1
rd print(glue('Round ', rd, ' The new sum of within-cluster distance is: ',
round(total_within_cluster_distance(df), 2)))
}
The initial centroid for point 3 was 3. It is now 1
The initial centroid for point 5 was 2. It is now 3
The initial centroid for point 6 was 3. It is now 1
The initial centroid for point 8 was 1. It is now 2
The initial centroid for point 10 was 1. It is now 2
The initial centroid for point 11 was 1. It is now 2
The initial centroid for point 12 was 2. It is now 3
The initial centroid for point 13 was 2. It is now 3
The initial centroid for point 14 was 1. It is now 3
The initial centroid for point 15 was 2. It is now 3
The initial centroid for point 16 was 1. It is now 2
The initial centroid for point 19 was 1. It is now 3
The initial centroid for point 20 was 3. It is now 2
The initial centroid for point 21 was 1. It is now 3
The initial centroid for point 23 was 1. It is now 3
The initial centroid for point 24 was 1. It is now 2
The initial centroid for point 25 was 1. It is now 3
The initial centroid for point 26 was 2. It is now 1
The initial centroid for point 28 was 1. It is now 3
The initial centroid for point 30 was 3. It is now 2
The initial centroid for point 31 was 1. It is now 2
The initial centroid for point 32 was 1. It is now 2
The initial centroid for point 33 was 2. It is now 3
The initial centroid for point 34 was 1. It is now 2
The initial centroid for point 35 was 2. It is now 3
The initial centroid for point 37 was 3. It is now 2
The initial centroid for point 38 was 2. It is now 3
The initial centroid for point 39 was 3. It is now 1
The initial centroid for point 44 was 2. It is now 3
The initial centroid for point 45 was 2. It is now 3
The initial centroid for point 48 was 2. It is now 3
The initial centroid for point 49 was 2. It is now 3
Round 2 The new sum of within-cluster distance is: 1594.37
The initial centroid for point 2 was 3. It is now 1
The initial centroid for point 3 was 1. It is now 2
The initial centroid for point 5 was 3. It is now 1
The initial centroid for point 9 was 3. It is now 1
The initial centroid for point 14 was 3. It is now 1
The initial centroid for point 17 was 1. It is now 3
The initial centroid for point 28 was 3. It is now 1
The initial centroid for point 37 was 2. It is now 3
The initial centroid for point 41 was 3. It is now 1
The initial centroid for point 44 was 3. It is now 1
Round 3 The new sum of within-cluster distance is: 1146.17
The initial centroid for point 7 was 2. It is now 3
The initial centroid for point 12 was 3. It is now 1
The initial centroid for point 32 was 2. It is now 3
Round 4 The new sum of within-cluster distance is: 1081.9
The initial centroid for point 18 was 2. It is now 3
Round 5 The new sum of within-cluster distance is: 1071.19
Round 6 The new sum of within-cluster distance is: 1071.19
print(centroid_loc)
# A tibble: 3 × 3
centroid mean_x mean_y
<int> <dbl> <dbl>
1 1 4.41 -4.99
2 2 -0.0601 5.27
3 3 -5.04 -5.47
ggplot(df, aes(x, y)) +
geom_point(aes(color = as.factor(centroid))) +
geom_point(data = centroid_loc, aes(x = mean_x, y = mean_y)) +
theme(legend.position = 'none')
<- kmeans(df[, 1:2], centers = 3,
yoo algorithm = 'Hartigan-Wong', nstart = 10)
$tot.withinss yoo
[1] 1017.417
library(broom)
<- df
df2 augment(yoo, df2) |>
ggplot(aes(x, y)) +
geom_point(aes(color = .cluster)) +
geom_point(data = as_tibble(yoo$centers), aes(x, y)) +
theme(legend.position = 'none')
The parameters
While using K-means, there are 3 main parameters one can tune.
- the number of clusters: this is the main one to tune to avoid both under-fitting (too low of a K) or over-fitting (to high of a K). If K = equal number of observation, of course the total within cluster variation will be 0 and minimized!
- the number of iteration
- the number of start
Number of clusters
The elbow method
The idea is to identify where does drop in the total within-cluster sum of square start to slowdown. Of course the total within-clusters sum of square decrease as the number of centroids increase. If we have n centroids (that is \(n = k\) - as many centroids as observations), the total within-cluster sum of square will be 0. And if we have only one centroid, the total within-one-cluster sum of square will be the sum of square of the mean of each of the variables.
So when does adding a centroid does not significantly reduce the total within-cluster sum of square.
The silhouette method
Number of iterations
Number of start
Vizualisation
A common trick is to use PCA and check the how well data are separated (in regards to their clusters) using the first 2 principal components dimensions.
Pro & Con
con
- You don’t always know in advance thee number of centroids. You can use the elbow method or the silhouette method to determine the numbers of centroids you want.
- because of the random initialization stage, results might not necessarily be reproducible. If results have to be reproduced, then you need to set a seed.


| Overview | Module | Use | Devguide | Index |
| Services' Summary | Interfaces' Summary | Properties' Summary | Services' Details | Interfaces' Details | Properties' Details |
|
|||
|
| Properties' Summary | |
| sequence< EnhancedCustomShapeParameterPair > Coordinates |
[ OPTIONAL ] This property is specifying the points that makes the geometry of the shape |
| sequence< EnhancedCustomShapeSegment > Segments |
[ OPTIONAL ] This property specifies the commands and the way the Coordinates have to be interpreted. |
| long StretchX |
[ OPTIONAL ] This property specifies the horizontal StretchPoint that has to be used. No stretching is used if this property is omitted. |
| long StretchY |
[ OPTIONAL ] This property specifies the vertical StretchPoint that has to be used. No stretching is used if this property is omitted. |
| sequence< EnhancedCustomShapeTextFrame > TextFrames |
[ OPTIONAL ] This property specifies the text frames that can be used with the shape. In general the first text frame is used, except the shape is containing vertical text, then the object tries to use the second text frame. The default text frame will be as big as the shape. |
| sequence< EnhancedCustomShapeParameterPair > GluePoints |
[ OPTIONAL ] This property specifies custom glue points |
| sequence< double > GluePointLeavingDirections |
[ OPTIONAL ] This property specifies GluePoint leaving directions. |
| short GluePointType |
[ OPTIONAL ] This property defines the GluePoint type. The values that can be used are specified in com::sun::star::drawing::EnhancedCustomShapeGluePointType |
| boolean ExtrusionAllowed |
[ OPTIONAL ] This property specifies if this shape supports the EnhancedCustomShapeExtrusion properties. The default is true. |
| boolean ConcentricGradientFillAllowed |
[ OPTIONAL ] This property specifies if this shape supports concentric gradient fill. The default is false. |
| boolean TextPathAllowed |
[ OPTIONAL ] This property specifies if this shape supports concentric gradient fill. The default is false; |
| Properties' Details | |
Coordinates
|
|
Segments
|
|
StretchX
|
|
StretchY
|
|
TextFrames
|
|
GluePoints
|
|
GluePointLeavingDirections
|
|
GluePointType
|
|
ExtrusionAllowed
|
|
ConcentricGradientFillAllowed
|
|
TextPathAllowed
|
Copyright © 2013, The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache, the Apache feather logo, Apache OpenOffice and OpenOffice.org are trademarks of The Apache Software Foundation. Other names may be trademarks of their respective owners.