Plug and Play Driver Test
Overview:
The
purpose of the
Plug and Play Driver test is to provide driver writers with a tool which exercises
various PnP related codes paths in the driver and user mode components. If used
in conjunction with Driver Verifier, driver writers can feel more confident
that their code is performing properly. This tool is for use on Windows 2000,
Windows XP, and Windows Server 2003.
Although
by using this tool a driver will be forced to handle almost all the PNP IRPs,
there are three areas that are stressed specifically – Removal, Rebalance, and
Surprise Removal. The test provides a mechanism to test each of these
separately or all together (i.e, stress). This is accomplished using a
combination of user mode API calls (via the test app) and kernel mode API calls
(via an upper filter driver).
The
first time the test is run, you will be prompted with UI for the location of
the test filter driver (pnpfiltr.sys). After pointing to the proper location
for the filter driver, its service will be installed and the driver copied. If
you have run an older version of the test previously, you may need to reboot
after the new filter driver is copied if the old driver is currently loaded.
Removal:
Device
removal is tested by selecting the target device and clicking the “Test
Removal” button. This encompasses IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
and IRP_MN_REMOVE_DEVICE.
The
test will attempt to install its upper filter driver on the target device
stack. This results in a query-remove IRP – if this query-remove is failed the
machine may need to be rebooted in order to get the filter driver onto the
device stack. If the remove request is not vetoed, the device stack will be
removed and restarted with the filter driver on the device stack.
The
test, using Setup APIs will cause a query-remove to be sent to the device stack.
The filter driver will fail this remove request thus causing a cancel-remove
IRP to be sent. The filter driver will assert that the cancel-remove was
successful.
Next,
the test app calls the appropriate class installer and any registered co-installers
to disable/enable and remove/reenumerate the device (this tests the
class/co-installers handling of DIF_PROPERTYCHANGE with DICS_DISABLE,
DICS_ENABLE, and DICS_PROPCHANGE). When receiving an IRP_MN_REMOVE_DEVICE, the
filter driver will assert that the lower drivers completed it successfully.
The
test will again call the class/co-installers this time with DIF_REMOVE and then
will reenumerate the device’s parent to attempt to restart the device. This
step essentially uninstalls the device as if you had used Device Manager.
Of
course, each of these steps involves a preliminary remove request. If that
request if vetoed, the device will not be removed. It is up to the driver
writer’s discretion to veto a remove request when appropriate, such as while
streaming video on a USB camera or if the target device is in the boot/paging
path. Bear in mind that simply failing all remove requests is generally not
good practice – it will not guarantee that driver will never receive a remove
since a remove IRP will still be issued after a surprise removal or if anyone
in the device stack fails a start IRP.
Rebalance:
Rebalance
is tested by selecting the target device and clicking the “Test Rebalance”
button. On pressing this button, a separate
window will come up. The desired mode of rebalance should be pressed from this
window.
As
with the removal test, the test application will attempt to add an upper filter
to the target device stack and then restart the device stack using SetupDiCallClassInstaller
with DIF_PROPERTYCHANGE. If this is not successful (i.e., if someone on the
target device stack failed the query-remove IRP) the machine may need to be
rebooted in order to test rebalance.
Depending
on the mode of rebalance chosen, the following test may take the following
possibilities:
1) Simple:
This option initiates a
rebalance procedure which results in the following Irps
to the device driver:
IRP_MN_QUERY_STOP_DEVICE
IRP_MN_QUERY_RESOURCE_REQUIREMENTS
IRP_MN_FILTER_RESOURCE_REQUIREMENTS
After this point, two different paths are possible:
a) If the device has no
resources (or if some driver in the stack fails the query stop), the cancel
stop is sent and rebalance is cancelled.
IRP_MN_CANCEL_STOP_DEVICE
b) If the device actually
consumes resources, the rebalance procedure is completed.
IRP_MN_STOP_DEVICE
IRP_MN_START_DEVICE
With this option, the
resources of the device do not change.
2) FailQueryStop:
This option initiates a
rebalance procedure but the filter driver deliberately fails the query stop. So
the order of Irps looks like
IRP_MN_QUERY_STOP_DEVICE:
(which is failed by the filter driver while coming up). This
results in cancellation of rebalance.
IRP_MN_CANCEL_STOP_DEVICE
With this option, the resources
of the device do not change
3) NewResources:
This
option initiates a rebalance and also manipulates the resource requirement of
the device to maximize the chances that actually new resources are allocated to
the device. It also helps a device with no resources to actually go through the
complete rebalance procedure:
First
the simple rebalance is started which results in following Irps
IRP_MN_QUERY_STOP_DEVICE
IRP_MN_QUERY_RESOURCE_REQUIREMENTS
IRP_MN_FILTER_RESOURCE_REQUIREMENTS
In response to this Irp, while going up, filter driver takes action based on
whether the device consumes any resources or not:
a) If the device has no
resource requirement, filter assigns a fake resource.
b) If the device has resource
requirement:
Then it tries to restructure
the resource requirement list in such a way that maximizes the probability of
changing the current assignment. For eg if a device
needs 2 bytes of memory anywhere between 00 to FF and currently is assigned
3A-3B, then modify such that the new resource requirement (in order of
preference) looks like 00-39 or 3C-FF or 3A-3B. Similarly if the device
resource requirement list has any alternate requirements, it will change their
order so the alternate requirement comes earlier in the list.
Now
the device should always complete the rebalance procedure.
IRP_MN_STOP_DEVICE
IRP_MN_START_DEVICE
(Here we get the new allocated resources.
If fake requirements were created, we mask the new resources from the actual
drivers)
4) Fail Restart:
This option initiates a
rebalance but when the filter driver gets the start after the rebalance, it
deliberately fails it –which causes surprise removal Irp
followed by Removal Irp.
First it starts the rebalance
procedure and makes sure that the driver gets a stop and a start by generating
fake resource requirement for a device which does not consume any resources.
 This causes surprise remove irp.
IRP_MN_SURPRISE_REMOVAL
IRP_MN_REMOVE
After
the rebalance test is complete, the device will be uninstalled and
reenumerated, also removing the filter driver from the stack.
Double Start (Note:
Not supported by all devices):
Double
Start is tested by selecting the target device and clicking “Test Double
Start”.
As
with the removal test, the test application will attempt to add an upper filter
to the target device stack and then restart the device stack using SetupDiCallClassInstaller with DIF_PROPERTYCHANGE. If this
is not successful (i.e., if someone on the target device stack failed the
query-remove IRP) the machine may need to be rebooted in order to test
rebalance.
This option creates a
scenario in which a driver gets two start IRPs
without getting a stop in between. This option is not included as part of
stress. This test should be run, if you think your
driver should be capable of handling this case. In this case, the filter driver
tells the pnp manager that
resources have changed but does not want the device stack to be stopped.
This will result in
(IRP_MN_START – When device
started, it must have got this)
IRP_MN_QUERY_RESOURCE_REQUIREMENTS
IRP_MN_FILTER_RESOURCE_REQUIREMENTS
IRP_MN_START_DEVICE
After
the double start test is complete, the device will be uninstalled and reenumerated, also removing the filter driver from the
stack.
NOTE: ‘Double Start’ is not included it as part of
stress. Driver writers should run this test separately if they want to test the
driver for such a scenario.
Surprise Removal:
Surprise
removal is tested by selecting the target device and clicking “Test Surprise
Removal”. This encompasses
IRP_MN_SURPRISE_REMOVAL followed by IRP_MN_REMOVE_DEVICE.
As
with the previous tests, the test application will attempt to add an upper
filter to the target device stack and then restart the stack. If this is not successful
the machine may need to be rebooted in order to test surprise removal.
When
triggered by the test application, the filter driver will cause the system to
send an IRP_MN_SURPRISE_REMOVAL to the device stack, followed by an IRP_MN_REMOVE_DEVICE.
The filter driver will assert that both of these IRPs are completed
successfully by lower drivers.
NOTE: On Windows 2000 only, after handling the surprise
removal IRP, the device will be marked by the system with the status code
DN_HAS_PRIVATE_PROBLEM. The device will still appear in the device tree in
Device Manager because, since it has not actually been physically removed, it
will still be reported by its bus driver in response to an
IRP_MN_QUERY_DEVICE_RELATIONS for BusRelations. In order to restore the device
to working order, the PDO for the device must be deleted. This can be
accomplished by rebooting the system, removing and reenumerating the device’s
parent, or physically removing the device and reattaching it. On Windows XP and
above, the OS can handle this properly and the test should be able restart the
device successfully, unless an error occurred.
After
the surprise removal test is complete, the device will be uninstalled and
reenumerated, also removing the filter driver from the stack.
Stress:
All
of the above scenarios (except for ‘Double Start’) can be tested together by
selecting the target device and clicking “Start Stress”). The test application
will keep choosing one of the above tests (remove,
surprise remove or one of the rebalance tests) and running it on the selected
device for five minutes.
Automation:
Pnpdtest offers command line options to run all the above
options and some other extra options for stress.
Pnpdtest [ /device
<service> | <HW ID> | <Device Instance> | <All>
]
[ /driverpath
<Filter driver directory> ] [ /stress ] [ /rebalance [mode] ]
[/log <LogFile>]
[/surprise] [/remove] [/doublestart]
[ /timedstress
<minutes> ] [ /NoDbgBreak
] [ /? ]
Pnpdtest /cleanup
/device: Specifies
the device by either its Service name, Hardware ID, or
Device instance Id, on which to carry out the tests. If “All” is given as the
device name, then the selected test is run on all the devices on the system.
This parameter is necessary for automation.
/driverpath: Specified the path of the directory
where filter driver file is present. The driver file name should not be
included in the path. If the path is not correct the test will look in the
system32\drivers directory – and if it can not find the driver there also, then
it will popup the open file dialog.
/log: Create
the log file with the name specified. The name should contain the full path.
/nodbgbreak: If this parameter is used, then the test
does not break into the debugger when the filter driver detects that a PnP IRP has
failed, which should have been succeeded. It just logs in the logfile.
/remove: Run Remove Test
/surprise: Run Surprise Remove Test
/ rebalance: Run
Rebalance Test, where optional mode can be:
FailQueryStop: Fail the Query Stop Irp
NewResources: Try to change allocated resources or create
fake requirement
FailRestart: Fail the start irp
which comes after stop
/doublestart: Run Double Start Test ( This option is not run as part of the stress ).
/stress: Run
the stress option. It will run different tests (remove, surprise remove or one
of the rebalance tests) on the selected device for five minutes. If “All” is
used as an option , it will go through the device list
and run stress (5 minutes on each device) on those devices , on which filter
driver can be installed without requiring a reboot.
/ timedstress: Run stress for the specified amount of
time in minutes. With this option, first creates a list of devices on which
filter driver can be installed without a reboot. This can take some time, depending
on the number of devices in the system. Then it continuously selects a random
device from that pruned list and runs a random test on it. The only other
options that can be used with this option are /driverpath
and /nodbgbreak.
/cleanup: Remove
the test filter driver from all the devices on the system. This should be
typically used to cleanup after all the tests have been run, especially for
cases where test terminated in an unexpected fashion. If this parameter is used
– then no other parameters should be used.
/?: Display help
Pnpdtest uses WTTLogging to log results. It creates
two log files – one in plain text format called pnpdtest-log.txt and another
one in xml formal called pnpdtest-log.xml.trace to be
used with WTT.
Some
examples are:
pnpdtest /stress /device All /nodbgbreak /driverpath
c:\pnpdstress
Run
stress on all devices one by one, copying filter driver from c:\pnpdstress and
will not break in the debugger when a wrong PnP IRP is failed by the driver.
pnpdtest /remove /device “flpydisk”
Run
the remove test on all devices which have service name as flpydisk
pnpdtest /timedstress
120 /nodbgbreak /driverpath
c:\pnpdstress
Run
random tests on random devices for two hours, copying filter driver from
c:\pnpdstress and will not break in the debugger when a wrong PnP IRP is failed
by the driver.
pnpdtest /rebalance NewResources /device
“FDC\GENERIC_FLOPPY_DRIVE\5&c4ae404&1&0”
Run the rebalance test with newresources option on device with the
NOTE: pnpdtest
assumes that wttlog.dll exists in the path. It won’t run without it.


number octdec ( string $octal_string )
Returns the decimal equivalent of the octal number represented by the octal_string argument.
The decimal representation of octal_string


Publishing a project website to Github Pages
I recently was faced with moving the website of one of my Github hosted projects from its current non-Github location to Github Pages.
At first glance publishing a project website to Github pages appears fiddly and error prone because you have to bounce between normal code branches and the Github Pages branch which have completely different files and directory structures. This is even trickier when your project’s build workflow also builds your web pages (as mine does).
I initially tried git-subtree
techniques for GitHub Pages deployment (see here, here and here) but found them brittle and arcane. Then I came across this Github Gist which neatly solved the problem viz. keep your code branches in one local repository and the gh-pages
branch in another. Locate the Github Pages repo on an ignored gh-pages
sub-directory of the local code branches repository.
- Both local repositories use the same remote Github repository: the local code repository contains code branches, the local website repository contains only the
gh-pages
branch. - Typically the project build process generates the project website pages in HTML format which it copies to the local
gh-pages
sub-directory (along with any other generated webpage assets). - To publish the Github Pages repo:
- Change directory to the
gh-pages
sub-directory. - Commit the changes and push them to the
gh-pages
branch at Github. - Then cd back up to the project root and continue coding.
- Change directory to the
The steps to achive this are outlined below and were based on this Github Gist (the Gist assumes the gh-pages
branch already exists in the Github repo whereas my example does not).
Before starting it is assumed that:
- Your project code has already been published to Github.
- Your local project repository is up to date with the remote Github repo.
- The
gh-pages
branch has not yet been created either locally or remotely.
The following commands add a local repo in the gh-pages
sub-directory and then creates a gh-pages
branch which is pushed to Github (<username>
and <projectnames>
refer to your Github user name and project name respectively):
# Go to local project code repository.
$ cd myproject
# Code repo ignores the documentation repo.
$ echo gh-pages/ >> .gitignore
# Make another repo in gh-pages sub-directory.
# There is nothing magic about the sub-directory name, it can be anything you like.
$ git clone https://github.com/<username>/<projectname>.git gh-pages
# Create gh-pages branch and push it to Github.
# See https://help.github.com/articles/creating-project-pages-manually/
$ cd gh-pages
$ git checkout --orphan gh-pages
$ git rm -rf .
$ echo "Nothing to see yet, move along..." > index.html
$ git add index.html
$ git commit -am "First pages commit"
$ git push origin gh-pages
$ git branch -u origin/gh-pages # Track gh-pages branch on remote.
$ git branch -D master # We don't need code branches.
$ cd .. # Return to code repo.
The documentation can be viewed at http://<username>.github.io/<projectname>
(keep in mind that it can take up to 30 minutes for the web pages to appear at Github the first time after creating the gh-pages
remote branch).
If your project already has an existing gh-pages
branch the above can be reduced to:
$ cd <projectname>
$ echo gh-pages/ >> .gitignore
$ git clone --branch gh-pages https://github.com/<username>/<projectname>.git gh-pages
From here on you treat the local Github Pages repo just like any other Github repository except that when you push it to Gitub you use the gh-pages
branch name:
$ git push origin gh-pages
Here’s an example bash script that I use to automate deployment of the gh-pages
branch.
On a side-note, you can use a custom domain name for your project’s Github Pages website by adding a CNAME
file to the gh-pages
branch – see the Github documentation for details.


Steam Friend Callbacks¶
GetFriendCallback¶
Get reference to Friend Callback Object to assign callback events.
Name |
Type |
Description |
|---|---|---|
Return Value |
PFFriendCallbacks |
Pointer to friend callback handler. |
SteamGameOverlayActivatedCallback¶
When the steam ovberlay activates or deactivates. Can be used to pause or resume single player games.
Name |
Type |
Description |
|---|---|---|
bActive |
bool |
Returns true if steam overlay was activated, and returns false when steam overlay deactivated. |
EChatMemberStateChange¶
Name |
Value |
Description |
|---|---|---|
ChatMemberStateChangeEntered |
Entered (0x0001) |
The User has joined or is joining the lobby. |
ChatMemberStateChangeLeft |
Left (0x0002) |
The User has left or is leaving the lobby. |
ChatMemberStateChangeDisconnected |
Disconnected (0x0004) |
The User has disconnected from the lobby. |
ChatMemberStateChangedKicked |
Kicked (0x0008) |
The User has been kicked. |
ChatMemberStateChangeBanned |
Banned (0x0010) |
The User has been kicked or banned. |
SteamLobbyCreated¶
Result of a request to create a Lobby. Lobby has been joined and is ready for use at this point.
Name |
Type |
Description |
|---|---|---|
SteamLobbyResult |
Integer |
Result of the create lobby operation as an EResult. |
SteamLobbyID |
Integer |
Steam ID of the lobby. |
SteamLobbyEntered¶
Result of entering a lobby.
Name |
Type |
Description |
|---|---|---|
SteamLobbyID |
Integer |
Steam ID of the lobby. |
SteamLobbyBlocked |
bool |
When true only invited users may join. |
LobbyEnteredResponse |
Response to determine if lobby was entered successfully. |
ELobbyEnteredResponse¶
Name |
Value |
Description |
|---|---|---|
EResponse_Success |
Success (1) |
Successful entry to chat/lobby. |
EResponse_DoesntExist |
DoesntExist (2) |
Lobby/Chat doesn’t exist (maybe closed). |
EResponse_NotAllowed |
NotAllowed (3) |
Do not have permission to join. |
EResponse_Full |
Full (4) |
Chat/Lobby room is full. |
EResponse_UnexpectedError |
UnexpectedError (5) |
UnexpectedError. |
EResponse_Banned |
Banned (6) |
The User has been banned from this lobby/chat and cannot join. |
EResponse_Limited |
Limited (7) |
Cannot join this lobby because the user is limited. |
EResponse_ClanDisabled |
ClanDisabled (8) |
Attempt to join a chat when clan chat is locked or disabled. |
EResponse_CommunityBan |
CommunityBan (9) |
Cannot join this chat/lobby because the user is banned from the community |
EResponse_MemberBlockedYou |
MemberBlockedYou (10) |
Cannot join this chat/lobby because a member in this chat/lobby blocked you. |
EResponse_YouBlockedMember |
YouBlockedMember (11) |
Cannot join this chat/lobby because the user has blocked a user already in the chat/lobby |


{# external dependencies before they may be called by internal scripts #} {% if includes_bokeh %} {% set bkversion = bokeh_version | default('1.4.0') %} {% endif %} {% if includes_plotly %} {% endif %} {# internal script inclusions #} {# block injecting app config to the global sfa_dash_config object, passed through template_globals #} {# inject the page_data json variable if provided by jinja #} {% if page_data is defined %} {% endif %}


--- layout: post title: a rather unfortunate concept date: '2014-09-22T07:30:00+02:00' categories: - Sketches picture_url: https://film-Storyboards.tumblr.com/post/98140392420/a-rather-unfortunate-concept ---
A rather unfortunate concept…


Trader Sydnia:
What are you looking for? We sell only the best weapons, and we stand behind everything we sell here. Would you like to have a look around? I'm sure you'll find something you like. And I promise you that you won't find lower prices anywhere else!
Buy/Sell/Refund.
Ask about the local lord and tax rate.
Quest


Chapter 5 Visualizing: ggplot2
5.1 Why ggplot2?
This tutorial focuses exclusively on data visualization using ggplot2 because this package:
- provides a coherent language for visualizing data (vs. the original ‘plot’ function, which developed in an ad-hoc way)
- makes many tasks easier, such as: visualizing a third (z) variable; saving figures; automating plotting and formatting tasks
- creates beautiful figures and is flexible
You should really use ggplot2 for nearly all data visualization!
5.2 Additional resources for data visualization in R
The goal of this tutorial is to introduce you to the basics of ggplot2. I focus only on the features I use most often. We will barely scratch the surface of ggplot2’s functionality. But there are many resources that will help you learn more. Here are some of the ones I use:
- The official ggplot2 cheatsheet is amazing!
- Winston Chang’s book converted me from someone who was slightly confused by ggplot2 to a superuser….so I can’t recommend it enough! And, the associated website is great too.
- Hadley Wickham’s R for Data Science book, which is inspiration for much of this tutorial.
5.3 Objectives
- install the
ggplot2
package by installingtidyverse
- learn basics of ggplot2 with a dataset describing global ocean health
- practice writing a script in RMarkdown
- practice the rstudio-github workflow
5.4 Install tidyverse: tidyverse
We will use the ggplot2
package, which is bundled with a composite-package called tidyverse
. Check out tidyverse.org/ for more information.
We will download and install tidyverse
:
## from CRAN:
install.packages("tidyverse") ## do this once only to install the package on your computer.
You will see some messages describing which packages were installed with tidyverse
. Messages about name conflicts are also returned. This is not a problem its just an alert that two functions from dplyr will replace functions in the built-in stats package with the same name.
5.5 Create an RMarkdown file to work from
To do: Create a new R Markdown file
We will create the RMarkdown file you will be working from. You can write notes to yourself in Markdown and have a record of all your R code.
Go to File > New File > R Markdown … (or click the green plus in the top left corner).
Next, replace all the automatic text with the following:
---
title: "Graphics with ggplot2"
author: "Julie"
date: "11/21/2017"
output: html_document
---
# Learning ggplot2
We're learning ggplot2 It's going to be amazing.
Now, let’s save the file. I’m going to call my file ggplot2.Rmd
. Do a pull…then stage/commit (to save to git history)…then push to sync with GitHub.com.
5.6 Load the tidverse
We have downloaded the tidyverse package but it is not yet loaded in the R workspace. We will use the library()
function to load tidyverse. This will be the first code chunk in your RMarkdown:
library(tidyverse) ## do this every time you restart R and need it
5.7 Load and explore data
We will load the dataset we will be using for this tutorial into our workspace directly from GitHub.com (I always find this GitHub functionality so cool!).
ohi_data <- read_csv("https://raw.githubusercontent.com/OHI-Science/data-science-training/master/data/OHI_global_data.csv")
These data are from the global Ocean Health Index which assesses the condition of marine resources for 220 countries or territories.
The dataset includes:
| variable | description | data type | examples |
|---|---|---|---|
| country | OHI region name for country or territorial regions with marine coastline | character | Jarvis Island, Italy |
| OHI_score | Ocean Health Index scores describing condition of marine resources based on the 2017 global assessment | numeric | values can range from 0-100, with 100 being the best possible score |
| OHI_trend | average annual change in OHI scores from 2012 to 2017 | numeric | values range from -3.9 to 1.86, with positive values indicating improving scores |
| coastal_pop | human population within 25 miles of coast | numeric | values range from 0 to >317 million |
| log_coastal_pop | log(coastal_pop + 1) | numeric | values range from 0 to ~20 |
| cumulative_human_impact | average cumulative impact of human stressors (e.g., SST, shipping, pollution) on marine ecosystems within the country’s marine boundaries | numeric | values range from 1.419 to 6.762, with larger values indicating higher impact |
| HDI | Human Development Index scores, which measure average achievement in key dimensions of human development: a long and healthy life, being knowledgeable and have a decent standard of living. | numeric | values are rescaled to be between 0 to 1, with higher scores indicating better human development |
| georegion_one | lower resolution UN georegion designations based on georegional and social similarities | character | Africa, Americas, Asia |
| georegion_two | higher resolution UN georegion designations based on georegional and social similarities | character | Australia and New Zealand, Eastern Asia, Caribbean |
Let’s explore these data, shall we:
head(ohi_data)
## # A tibble: 6 x 9
## country OHI_score OHI_trend coastal_pop log_coastal_pop cumulative_huma…
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 South … 92.0 1.67 0 0 2.82
## 2 Crozet… 88.1 0.81 0 0 1.92
## 3 Howlan… 87.7 0.08 0 0 2.97
## 4 Heard … 87.4 0.46 0 0 2.78
## 5 Kergue… 87.3 0.72 0 0 2.02
## 6 Jarvis… 83.9 -0.25 0 0 1.85
## # … with 3 more variables: HDI <dbl>, georegion_one <chr>,
## # georegion_two <chr>
summary(ohi_data)
## country OHI_score OHI_trend coastal_pop
## Length:221 Min. :41.83 Min. :-3.9900 Min. : 0
## Class :character 1st Qu.:61.62 1st Qu.:-0.5600 1st Qu.: 106224
## Mode :character Median :67.82 Median :-0.1800 Median : 1066507
## Mean :66.87 Mean :-0.2261 Mean : 11471246
## 3rd Qu.:72.21 3rd Qu.: 0.1900 3rd Qu.: 7081969
## Max. :91.98 Max. : 1.8600 Max. :317149893
##
## log_coastal_pop cumulative_human_impact HDI
## Min. : 0.00 Min. :1.419 Min. :0.4140
## 1st Qu.:11.57 1st Qu.:3.553 1st Qu.:0.5970
## Median :13.88 Median :3.896 Median :0.7400
## Mean :12.64 Mean :3.861 Mean :0.7159
## 3rd Qu.:15.77 3rd Qu.:4.351 3rd Qu.:0.8270
## Max. :19.57 Max. :6.762 Max. :0.9490
## NA's :76
## georegion_one georegion_two
## Length:221 Length:221
## Class :character Class :character
## Mode :character Mode :character
##
##
##
##
table(ohi_data$georegion_one)
##
## Africa Americas
## 46 3
## Asia Europe
## 40 43
## Latin America and the Caribbean Oceania
## 48 34
## Southern Islands
## 7
table(ohi_data$georegion_two)
##
## Australia and New Zealand Caribbean
## 6 28
## Central America Eastern Africa
## 9 17
## Eastern Asia Eastern Europe
## 6 5
## Melanesia Micronesia
## 5 13
## Middle Africa Northern Africa
## 7 7
## Northern America Northern Europe
## 3 19
## Polynesia South America
## 10 11
## South-Eastern Asia Southern Africa
## 12 2
## Southern Asia Southern Europe
## 7 14
## Southern Islands Western Africa
## 7 13
## Western Asia Western Europe
## 15 5
5.8 Plotting with ggplot2
Plots are created using a step-wise approach that is flexible and easily customized. We will walk through the steps needed to build a plot in ggplot2.
HINT: Start with the simplest version of your plot and build onto it.
5.8.1 Step 1: Identify the dataframe
ggplot2 requires the data to be in a dataframe format. The first step is to use the ggplot()
function to identify the dataframe with the data you want to plot.
At this point, we will also assign the x and y axis variables within the aes function (this stands for aesthetics, and we will discuss this concept after we have a plot to work with).
[NOTE: This step was confusing for me for a long time because it doesn’t actually make the plot!]
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI))
5.8.2 Step 2: Identify the style of plot you want to create (i.e., the geom)
Next, we will actually create the plot by adding a geom function using the +
operator. A geom is the geometrical object that a plot uses to represent data. For example, bar charts use bar geoms, line charts use line geoms, boxplots use boxplot geoms, and so on.
You can use different geoms to plot the same data. To change the type of plot, change the geom function that you add to ggplot()
.
ggplot2
provides over 30 geoms, which are described in the official ggplot2 cheatsheet. To learn more about any single geom, use help: ?geom_smooth
. Extension packages provide even more geoms (see https://www.ggplot2-exts.org for a sampling).
We will start by creating a scatterplot of ohi scores within UN georegions by adding the geom_point
function.
ggplot(data = ohi_data, aes(x = georegion_one, y =OHI_score)) +
geom_point()
Yay! A plot!
Next we will replace geom_point() with geom_jitter() to create a style of plot with the same data. geom_jitter is similar to geom_point, but it adds random variation to values along the x-axis to separate points:
ggplot(data = ohi_data, aes(x = georegion_one, y =OHI_score)) +
geom_jitter(width=0.2) # the width argument describes how much scatter to add
Now we will explore other geoms.
The following bar plot uses geom_bar to describe the number of countries in each UN category:
ggplot(data = ohi_data, aes(x = georegion_one)) +
geom_bar()
A histogram using geom_histogram:
ggplot(data = ohi_data, aes(x = HDI)) +
geom_histogram()
Multiple geoms can be layered on the same plot. Geom layers can be added using either the same or different dataframes. To demonstrate this we will use a secondary dataset with the mean OHI score for each UN georegion. We will create a bar plot of the means for each region and then overlay the point data.
ohi_summary <- read_csv("https://raw.githubusercontent.com/OHI-Science/data-science-training/master/data/OHI_scores_georegion_summary.csv")
ohi_summary
## # A tibble: 7 x 2
## georegions OHI_score_average
## <chr> <dbl>
## 1 Africa 59.7
## 2 Americas 68.3
## 3 Asia 63.9
## 4 Europe 68.5
## 5 Latin America and the Caribbean 67.0
## 6 Oceania 75.0
## 7 Southern Islands 80.1
ggplot(data = ohi_summary, aes(x = georegions, y = OHI_score_average)) +
geom_bar(stat="identity") +
geom_jitter(data=ohi_data, aes(x=georegion_one, y=OHI_score))
In the above example, the global mappings are designated by: ggplot(data = ohi_summary, aes(x = georegions, y = OHI_score_average))
. These are then overwritten by the local mappings designated in the geom_jitter layer. The global designations will apply to subsequent layers, unless otherwise changed. This makes it possible to display different aesthetics and data in different layers.
STOP: let’s Commit, Pull and Push to GitHub And discuss the following
- In the code below, why isn’t the data showing up?
ggplot(data = ohi_data, aes(y = OHI_score, x = HDI, color=georegion_one))
- Are these two approaches the same?
ggplot(data = ohi_data, aes(y=OHI_score, x = HDI, color=georegion_one)) +
geom_point()
ggplot(data = ohi_data) +
geom_point(aes(y = OHI_score, x = HDI, color=georegion_one))
Answers
- The code is missing a geom to describe how the data should be plotted.
- These two approaches result in the same plot here, but there could be downstream effects as more layers are added.
More about the aes function
The arguments within aes()
link variables in the dataframe to some aspect of plot appearance. As we have discussed, x and y describe the axes, but other arguments can be added to describe a z variable (e.g. size or color or shape of points). Here are some examples of aes arguments:
- color color of lines/points
- fill color within polygons
- label name
- linetype type of line
- shape style of point
- alpha transparency (0-1)
- size size of shape
This is very powerful! Let’s explore.
Changing the point size:
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, size = coastal_pop)) +
geom_point()
Changing the color: continuous variable
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, color = coastal_pop)) +
geom_point()
Changing the color: discrete variable
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, color = georegion_one)) +
geom_point()
Changing shape of points
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, shape = georegion_one)) +
geom_point()
Adding labels
#This doesn't add the labels like it seems like it should:
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, label=country)) +
geom_point(aes(x = OHI_score, y = HDI))
# To do this we have to add a geom_text function
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, label=country)) +
geom_point(aes(x = OHI_score, y = HDI)) +
geom_text()
5.8.3 Step 3: Customize your plot
So far, the plots we have created are fairly ugly and hard to read. We will now improve these basic plots using a stepwise approach.
<IP_ADDRESS> Themes
I do not like the default ggplot2 figures because I find them too busy. A quick way to improve plot appearance is to use themes. Many themes are built into the ggplot2
package. For example, theme_bw()
removes the gray background. Once you start typing theme_
a list of options will pop up.
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI)) +
geom_point() +
theme_bw()
The ggthemes package provides many additional themes (including a Tufte theme..which is very clean and data oriented). The ggplot2
extensions website provides a list of packages that extend the capabilities of ggplot2
, including additional themes.
I often create my own themes to make figures that work well in publications or presentations. This also gives my figures a consistent look (without having to remember from figure to figure the size of labels, etc.). I have found that storing my themes on Github works well. Here is an example of a theme I created named “scatterTheme”:
source('https://raw.githubusercontent.com/OHI-Science/ohiprep/master/src/R/scatterTheme.txt')
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI)) +
geom_point() +
scatterTheme
<IP_ADDRESS> Labels: axis, plot, legend
One of the first things you will often want to do is alter labels for: titles, axes, figure legends, etc. These modifications involve manipulating the theme function and can quickly get complicated, and I typically have to Google the specifics or refer to a cheatsheet, despite using ggplot2 for years and years and years.
But, some key changes are easy to make using the labs function:
ggplot(data = ohi_data, aes(y = OHI_score, x = HDI, color=georegion_one)) +
geom_point() +
labs(y = "OHI score, 2017",
x = "Human Development Index",
title = "Countries with high human development have more sustainable oceans",
color = "Georegion") + # if color doesn't work, use "fill"
theme_bw()
We interrupt this section on customizing your plot for an exercise (5 min)
- Make a histogram of the OHI_score variable and color by the georegion_one variable.
- How would you make all the bars on your histogram light gray? Hint: use argument
fill = "lightgray"
. Where is the best place to add this in your code to get this to work? - Play with some themes and customizing title and axes labels. Try changing the text sizes and angles (refer to the cheatsheet).
Answers (no peeking)
# 1. This one is tricky because the color aesthetic only does the outline of the bars.
# If you got that far, you were halfway there.
# You will need to use the fill argument to color shapes
my_plot <- ggplot(data = ohi_data, aes(x=OHI_score, fill=georegion_one)) +
geom_histogram()
my_plot
# 2. This was something that confused me for a while. My instinct was to add it to the aes function....BUT NO!!!
# The arguments in aes should correspond to a column in the dataframe. The best place for this argument is in
# the geom function (and not in an aes function)
ggplot(data = ohi_data, aes(x=OHI_score)) +
geom_histogram(fill="lightgray")
# 3.
my_plot + # the plot created in question 1 continued...
labs(x = "OHI score",
y = "Number of countries",
title = "Distribution of OHI scores") +
theme_light() +
theme(legend.title = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1, size = 14),
axis.text.y = element_text(size = 14),
axis.title = element_text(size = 16)
)
STOP: commit, pull and push to github
We will now continue with customizing your plot…..
<IP_ADDRESS> Global changes to plot attributes
It is easy to make global changes to your plot’s appearance (these go outside the aes function). Here are some options:
- color color of lines/points
- fill color within polygons
- label if points are a character
- linetype type of line
- shape style of point
- alpha transparency (0-1)
- size size of shape
Here are the R shapes with their reference numbers:
Here are the R line types with their reference numbers:
With this information, we can improve the appearance of one of our previous figures:
ggplot(data = ohi_summary, aes(x = georegions, y = OHI_score_average)) +
geom_bar(stat="identity", fill = "lightgray") +
geom_jitter(data=ohi_data, aes(x=georegion_one, y=OHI_score), color="red", size=3, alpha=0.3) +
theme_bw()
<IP_ADDRESS> Color
One of the more challenging aspects of creating a good plot is selecting colors. We are here to help!
Hint 1 Unless you are doing something very simple (e.g. 1-3 colors), I recommend using established color palettes. There are many color palette packages (here is a good resource: https://github.com/EmilHvitfeldt/r-color-palettes), but one of the best known is RColorBrewer.
Here we will explore using the RColorBrewer palettes.
Install the RColorBrewer and colorspace packages (only needs to be done once). Both RColorBrewer and colorspace have nice palettes and colorspace has additional functions for dealing with color.
install.packages("RColorBrewer")
install.packages("colorspace")
Load packages into working space:
library("RColorBrewer")
library("colorspace")
To see the available palettes in RColorBrewer:
display.brewer.all()
To select a palette:
my_palette <- brewer.pal(n=9, "YlOrRd")
Hint 2 R uses hexidecimal to represent colors. Hexadecimal is a base-16 number system used to describe color. Red, green, and blue are each represented by two characters (#rrggbb). Each character has 16 possible symbols: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
“00” can be interpreted as 0.0 and “FF” as 1.0, i.e., red= #FF0000 , black=#000000, white = #FFFFFF
Two additional characters (with the same scale) can be added to the end to describe transparency (#rrggbbaa)
A color palette is actually just a simple vector of hexidecimal values:
my_palette
## [1] "#FFFFCC" "#FFEDA0" "#FED976" "#FEB24C" "#FD8D3C" "#FC4E2A" "#E31A1C"
## [8] "#BD0026" "#800026"
I always use hexidecimal format for colors in R because it is the most direct approach.
Hint 3 The function you will want to use to specify color in ggplot2 depends on whether the color is mapped to a discrete/categorical data variable, or a continuous variable. There are a LOT of options in ggplot2, but these are the approaches I have settled on because they are the most flexible:
In the following case we map color to a continuous variable, so we will use the scale_color_gradientn function with the palette we selected above:
ggplot(data = ohi_data, aes(x = OHI_score, y = OHI_trend, color = HDI)) +
geom_point(size =3) +
scale_colour_gradientn(colors = my_palette)
This function takes a vector of colors and interpolates between the colors to get a gradient.
If we are mapping color to a discrete variable, we will use the scale_color_manual function:
# lets use a discrete color scale
my_palette <- brewer.pal(n=12, "Set3")
ggplot(data = ohi_data, aes(x = OHI_score, y = HDI, color = georegion_one)) +
geom_point(size = 3) +
scale_color_manual(values = my_palette)
# Note the first 7 of the 12 colors are used in the plot
The scale_color_manual function also has a lot of great arguments that allow you to control which colors are associated with each factor level, the names used in the legend, and other controls.
Hint 4 If the “color” functions aren’t working, try the “fill” version of the function.
Challenge
With all of this information in hand, please take a few minutes to create a plot using the fake dataset we will create below (or one of the other datasets we have worked with).
# making a fake dataframe
fake_data <- data.frame(animal = rep(c("cat", "dog", "hamster"), each=10),
year = 2011:2020,
values = c(rnorm(n=10, 5, 1) * seq(0.1, 0.5, length.out=10),
rnorm(n=10, 8, 1) * seq(0.1, 0.5, length.out=10),
rnorm(n=10, 10, 1) * seq(0.1, 0.5, length.out=10)))
## Add your code to create a plot:
Answers (no peeking!)
Here is one approach, but there is a lot more to do to make this really nice!
library(ggthemes)
ggplot(data = fake_data, aes(x = as.factor(year), y = values, group=animal, color=animal)) +
geom_point(size = 3) +
geom_line(size=2, alpha = 0.5) +
labs(x = "year", color = "") +
theme_tufte()
5.9 Saving plots
After creating your plot, use the ggsave()
function to save your plot. This function allows you easily change the dimension, resolution, and format of your plot:
my_plot <- ggplot(data = fake_data, aes(x = as.factor(year), y = values, group=animal, color=animal)) +
geom_point(size = 3) +
geom_line(size=2, alpha = 0.5) +
labs(x = "year", color = "") +
theme_tufte()
ggsave("name_of_file.png", my_plot, width = 15, height = 10, dpi=300)
Note: The parameters width
and height
also determine the font size in the saved plot.
5.10 Arranging plots
I am a huge fan of cowplots for making multiplot figures. Here is a nice introduction.
install.packages("cowplot")
library(cowplot)
## Error in library(cowplot): there is no package called 'cowplot'
score_vs_trend <- ggplot(data=ohi_data, aes(x=OHI_score, y=OHI_trend)) +
geom_point(size=3, alpha=0.4)
score_vs_trend # notice that the default theme has been changed....I really like this theme!
score_vs_HDI <- ggplot(data=ohi_data, aes(x=OHI_score, y=HDI)) +
geom_point(size=3, alpha=0.4) +
geom_smooth()
plot_grid(score_vs_trend, score_vs_HDI, labels = c('A', 'B'))
## Error in plot_grid(score_vs_trend, score_vs_HDI, labels = c("A", "B")): could not find function "plot_grid"
5.11 Interactive plots
So as you can see, ggplot2
is a fantastic package for visualizing data. But there are some additional packages that let you make plots interactive. plotly
, gganimate
. I use plotly all the time to check my data!
install.packages("plotly")
library(plotly)
## Error in library(plotly): there is no package called 'plotly'
score_vs_HDI <- ggplot(data=ohi_data, aes(x=OHI_score, y=HDI, text=paste0("Country: ", country))) +
geom_point(size=3, alpha=0.4)
ggplotly(score_vs_HDI)
## Error in ggplotly(score_vs_HDI): could not find function "ggplotly"


AT FIRST SIGHT A film review by Matt Williams
RATING: * * 1/2 out of * * * *
Oliver Sacks' story To See and Not See, a true account regarding restoring sight to the blind must have seemed like the perfect idea for a movie. Not only does an actor get to stretch his chops as a blind man, but the "miracle cure" would be, by definition, an uplifting moment. Both of these are true of At First Sight, but the film isn't happy to leave good enough alone. Instead, the film is saddled with a romantic subplot that proves unmoving and distracting.
Virgil Adamson (Val Kilmer) lost his sight between the ages of 1 and 3 due to congenital cataracts. Since then, under the protective wing of his elder sister Jennie (Kelly McGillis), he has made a life for himself as a massage therapist at a local resort.
However, everything is about to change when Amy Benic (Mira Sorvino) enters his life. She's an architect from New York who comes to the resort for a weekend getaway. She goes in for a massage, and winds up falling in love.
Back in New York, Amy discovers Dr. Charles Aaron (Bruce Davison), a surgeon with some radical ideas which just might be able to restore Virgil's sight. But, after living all his life without vision, will Virgil be able to relearn everything he knows about the world in order to see?
The medical drama of At First Sight, based on a true story, is easily the film's most compelling element. Though the premise at first feels a bit gimmicky, it is handled competently and with a good deal of thoughtfulness.
But At First Sight is hesitant to rely on the medical drama alone. Rather, it supplements the story with a romantic angle, and here is where it falters. The chemistry-free relationship between Mira Sorvino and Val Kilmer feels very artificial and lifeless.
Mira Sorvino is the prime culprit here. Her bland character is simply unappealing. Val Kilmer has the heftier role, and can always fall back on his character's visual dilemma for drama. Sorvino only has the romance to work with, and that's not a solid structure here at all.
In a delightful supporting turn, Nathan Lane briefly appears as a visual therapist. His few scenes in the film are such a welcome relief that it leaves you wondering how much better the film would have been without the overstressed romantic angle.
In the end, At First Sight is still worth watching...but there are plenty of better things to see.
Copyright 1999 Matt Williams
- Matt Williams<EMAIL_ADDRESS>Reviewer for Cinematter: http://www.cinematter.com Home of nearly 700 reviews, and information on over 750 upcoming releases
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


Introduction to Acre-Eye
While the applications of drone technology is nothing new and has been in commercial use for decades, their wide-scale applications continue to expand rapidly as innovators keep coming up with new ways to add value and make our lives easier. As drones become more prevalent in our society, much of this growth is attributed to not only declining costs of technology but also to the adjustments of government regulations on drone use. The agricultural industry has seen some major innovations in recent years due to the implementation of drone technology. The added benefits include scouting out new field locations, providing quick and easy ways to remotely check small sections of crops, and surveying entire fields. Drones are aiding farmers several of the developing challenges in the industry. The use of drones can help to increase productivity, permitting improved agricultural adaptation to the effects of climate change; they can also assist in the reduction of pollution.
Implementation of Drones
The number of farmers adopting drones in their farms is growing rapidly. Drones offer a cost-efficient way to monitor their crops. Using drones for farm management is far more complex than taking aerial photos and videos. Extracting useful information from the data gathered by drones involves a complex process that not all farmers may be willing to do. Below is a list of all the benefits and drawbacks of using drones for agriculture.
- Better data quality: Multispectral drone surveys have ushered in a new era of unequaled data quality and accuracy.
- Flexible analysis: Multiple multispectral surveys can be conducted in a single survey area to see changes over time of some useful parameters.
- Ease of deployment:Before drones, farmers who wanted to conduct aerial surveys of their farms had to use manned aircraft. Drones have reduced this need and increased simplicity.
- Crop spraying: Spraying using drones has also proven to be faster than other traditional methods.
Reduction in operational costs: Although using drones may involve a high start-up cost, it is still the more economical solution in the long run. Doing aerial surveys using manned aircraft will certainly be more expensive, as it will require more expensive equipment and more manpower.
Product Featuress
Lorem Ipsum
Voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident clarida perendo.
Dolor Sitema
Minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat tarad limino ata noble dynala mark.
Sed ut perspiciatis
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur teleca starter sinode park ledo.
Magni Dolores
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum dinoun trade capsule.
Dashboard Analytics
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit ese cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
System Architecture
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum.
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum.
Software Architecture
Several software components have been added to the project so far. That includes the frontend, backend as well as the raspberry pi modules.
Quis nostrud exercitaton ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum.
Quis nostrud exercitation ullamo laboris nisi ut aliquip ex ea commodo conseq. Dui aute irure dolor in reprehenderit in voluptate velit esse cilum.
The end goal is to integrate all of them together in the next development stage so that they all work together cohesively.
Drone Architecture
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Prototype Coming Soon!
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Dolor Sitema
Minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat tarad limino ata nodera clas.
Sed ut perspiciatis
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur trinige zareta lobur trade.
Magni Dolores
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum rideta zanox satirente madera
Our Team
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
Saffat Aziz
Scrum Master and System ArchitectKimberley Paradis
Product OwnerAdil Ughratdar
Frontend DeveloperAshar Asghar
Dev Ops EngineerRuchira Perera
ML EngineerAkif Manzoor
Backend DeveloperAcre-Eye
Cras fermentum odio eu feugiat. Justo eget magna fermentum iaculis eu non diam phasellus. Scelerisque felis imperdiet proin fermentum leo. Amet volutpat consequat mauris nunc congue.
801 king Edward Ave
Ottawa, ON 535022
<EMAIL_ADDRESS>+1<PHONE_NUMBER>


Hello, Aidar!
You (or someone who looks exactly like you) requested login verification code at 18 March 2019 21:45
The attempt was made from the following IP address: <IP_ADDRESS>
Please, verify this operation by putting verification code below
Do not send this code to someone. If you didn't this operation - please, change your password.
Contact us to order a turn-key solution for your crowdsale:


Preparation time
less than 30 mins
Cooking time
10 to 30 mins
Serves
Serves 4
This is a real store cupboard saviour. Pork mince can vary wildly in fat content, so make sure you check before buying. You could add more vegetables to this stew if you like - spinach, sweet potato, carrot or celery would all work. Chickpeas are a nice substitution for the beans, too.
Each serving provides 366 kcal, 27g protein, 44g carbohydrate (of which 7.5g sugars), 7.5g fat (of which 3g saturates), 7g fibre and 0.6g salt.
Mix together the pork mince, breadcrumbs, garlic granules, cumin, half the grated onion, plus a little salt and black pepper in a mixing bowl. Shape into 16 small meatballs and set aside.
Spray a large, lidded pan with a little spray oil and add the chorizo. Fry until the chorizo begins to create a little more oil in the pan, then add the rest of the onion and fry gently for a minute.
Add the tinned tomatoes, beans, chopped red pepper and half a tomato tin of water to the pan. Stir everything together and bring to a simmer. Put the meatballs carefully in the sauce, pushing them down with a spoon into the sauce.
Season with more black pepper, then partially cover the pan and simmer for 20 minutes. Uncover the stew as you cook the basmati rice according to the packet instructions. Serve the stew with the rice alongside.


DfE enquiries
Central newsdesk 020 7783 8300
General enquiries 0370 000 2288
News story
Nick Gibb: Too many children suffer the misery of being bullied on a daily basis.
Ahead of Anti-Bullying Week, Schools Minister Nick Gibb spoke to the News of the World about the importance of tackling bullying in schools:
Around half of all children say they’ve been bullied at school and had their lives blighted by fear. And it’s not just at school where young people encounter bullying.
It’s simply unacceptable for a child to be victimised - whether it’s in or out of school, or on their mobile phones, or on social networking sites like Facebook.
That’s why the coalition agreement that unites the government gives priority to tackling bullying and raising standards of behaviour in the classroom.
There are 3 clear principles behind the government’s position:
Our schools white paper later this month will put heads and teachers back in control, giving them a range of tough new powers to deal with bullies and the most disruptive pupils. Heads will be able to take a zero-tolerance approach and will have the final say - both in and outside of school.
We will also give teachers the right to remove disruptive children from the classroom without fear of legal action. They will be able to search pupils for weapons, and items like iPods and mobile phones, and confiscate them.
Schools will have revised guidance to make sure they know how to tackle bullying effectively.
We trust headteachers and teachers to use these powers. But there will be no-notice inspections for schools where behaviour, including bullying, is out of control.
As Schools Minister, I am determined to do everything I can to tackle bullying and to help schools raise standards of behaviour in the classroom.
Central newsdesk 020 7783 8300
General enquiries 0370 000 2288
Published: 15 November 2010


Press arrow keys to launch in different directions for more rockets
Rockets should not leave their confines
Compare with ex.Physics.checkForFastBodies = false


Looking for Government e-services for
citizens
?
To access Government e-Services and resources for individuals and families
Visit LifeSG


I want to share one facet of my trip, as I deem the rest of the trip too personal to be disclosed on this public message board. What I want to share is my realization, on a cellular level, what the word Dignity means, and what it means when that dignity is taken away from us humans. This experience made me surrender to the horrors of the most humiliation and degridation that my mind has ever known. I was forced to be stripped of any sort of self worth whatsoever almost hitting the 'cosmic bottom' of existence. It was the most intense experience of my life.
I realized on a cellular level that I have never actually harbored any Dignity for myself, None whatsoever in my real life. The fact that I had to experience, on a cellular level, not only my lack of Dignity, but the Humiliation and suffering of the Human race as a whole, was the absolute Maximum I have ever suffered in my life.  I fought not once.
Once I was completely humiliated, I took the role of a Teen-Age woman in a concentration camp during WWII. She had the words 'Feld Hure' (field whore) with SN A135633 Tattooed between her breasts. She was 'recruited' in the concentration camp to -pleasure- the German men coming to have some fun before they go back to the fighting on the front lines. She was instructed to Smile and be happy, If she was reported 3 times for not being this way, she would be killed.  My God.  And I was also able to look at the whole insanity of the situation from the 3rd person, as a complete outsider.
I have never cried so hard and uncontrollably in my life. I picked up a movie entitled 'The death camps' with a picture on the cover. The picture was the men in the concentration camps, the looks on their faces. I cannot describe in words the absolute fury and insanity I felt for any Man or Woman throughout time who has had thier DIGNITY stripped away from them. At that moment I became a Fighter, I am not a light worker anymore. I am a light Warrior. At that moment 'My adventure of self discovery' ended.
It has become an evolutionary step for mankind. I am going through this pain and suffering for all those people you see in amnesty international files. Those people who have been torchured, oppressed, and thier dignity stripped from them. I continue this Journey For Humanity not for myself. For My Brothers and Sisters. I am a light warrior.
 I have Dignity God damnit. And I will graduate not so much for me, but for my fellow man who has never had the chance at education. For Trancendence of ignorance and a push towards a higher Realm of existence. I will continue doing this for Mankind. I have no hope anymore, I realized it was fake magical thinking. I will just exist and be pushed and pulled wherever. But I will still be here, And I will have DIGNITY.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Some thoughts
If you like this post and would like to read more of my posts,
Subscribe!In a stark departure from my usual posts, here is some utterly unscientific nonsense that I mull over from time to time:
- You can convince people to believe you are great, if others simply keep repeating that you are. What’s even more surprising, is that you can even do this without the help of others. Simply praise yourself all day, everyday, and take credit for accomplishments that have involved great help from others. It’s even possible if you had nothing to do with the thing in question, and only in some cases is this fraud. However, this is morally wrong, without question (in my book). Which brings me to my next point.
- If you wish to be moral, you will get beaten out by someone who doesn’t. Ideally, we would want to stick to our morals all the time. However, being moral is effectively placing a restriction on yourself (like a tax), and one which in most cases leaves little to no benefit other than the upholding of morality. The thin line between morality and legality - sometimes even wandering into legality - is where many “successful” (see previous point) people operate.
- If one wishes, they can easily manipulate others. In fact, this is essentially what Dale Carnegie’s book How to win friends and influence people is about. What is more incredible, to me, is that you can even manipulate yourself! I once tried an experiment on myself, where I repeatedly told myself something I didn’t think to be true (that I thought had a < 5% chance of being true). After 2 weeks, I ended the experiment expecting to go back to normal. However, I couldn’t snap out of believing what I used to believe. Unrelated to my next point.
- I believe there are 10x engineers, or even 100x engineers. In other fields of individual pursuit - like sports - there are individuals who are clearly more skilled/capable/talented than others, and this is a non-controversial opinion. As of 2022, I do not see why this would not apply to engineering. Which brings me to:
- One person can - and has - changed the world. This has happened multiple times in history, and will continue to happen again. For examples, Newton, who revolutionized optics, calculus, physics and other fields, Galois who transformed mathematics before dying at 20 and Ramanujan, whose work I do not understand. Understanding? Ah,
- Assuming human intellect is likely on a bell curve (similar to genetic traits like height), it must be really frustrating for people much smarter than me to explain stuff to me. I can see this sometimes because so many concepts are so elementary to them that while their explanations flow, I flounder like a fish on land.
- Hard work can, and does, help. I assume “intellect” lies on a bell curve, but that only serves as a potential or some kind of “max limit” you could reach. This range lies much higher than where most people are, and that is because hard work determines how much of that potential you hit. Now, does the capacity for hard work lie on a bell curve?
- There is nothing wrong with saying “I don’t know” in response to a question, and that is the right answer for most people for most questions
- Social media optimizes for engagement, but when social media companies celebrate daily active users, it is a bit like celebrating giving sugar to a baby (or even an adult). Of course people will love never-ending short form video that supplies unlimited dopamine
- Empathy can go a long way. Would never have thought it ten years ago, but empathy can change a person’s mind more effectively than anything else.
- Many men are immature (or more comfortable being immature?) compared to women, and this might stem from the power disparity in society (which may stem from the power disparity in physical strength).
- Creating the best form of the argument you are responding to, before responding to it, is a great way to have a discussion rather than an argument.


New project
{% if error %}
{{ error }}
{% endif %}
Creating project
The project is being created and the models are being trained with the dataset. This could take a while. (A basic rule is that the larger the training file, the longer the wait time.)
When finished you will automatically be redirected. Otherwise you may leave this page and check back in your projects page. Your new project will appear as soon as this step is done.


--- layout: documentation title: NatureOfSecurityEffectType ---
| Field Name | Type | Description |
|---|---|---|
| Property_Affected0..n | PropertyAffectedType |
The Property_Affected field is optional and characterizes how a particular security property of the Asset was affected. |


RAMADDA User Guide
Page Styles
Section 6: Integrated Map Data Viewer (IMDV)
IMDV Introduction
+callout-info RAMADDA provides an Integrated Map Data Viewer (IMDV) entry type that supports the creation of rich interactive maps. There are numerous examples on
ramadda.org
. -callout
6.0
IMDV Introduction
6.1
Map Files
6.2
IMDV Images
6.3
Making Routes
6.4
IMDV Entries
6.5
The Multi-Entry Glyph
6.6
Data Icons
6.7
Custom Data Icons


--- layout: static title: Eagle Rex Cycling Club - 404 description: Eagle Rex is a friendly and diverse cycling club, founded in 2021 and based in London, UK. keywords: eagle rex, cycling club, bicycle clubs, bike club, cycling group, london, uk image: /assets/images/logo.png author: Sebastian Rousseau permalink: /404.html categories: [cycling club] tags: [eagle rex, cycling club, bicycle clubs, bike club, cycling group, london, uk] status: publish type: page published: true meta: { eagle rex, cycling club, bicycle clubs, bike club, cycling group, london, uk} date: May 1, 2021 robots: all ---


class to manipulate the web apps interface for reading and writing Google Sheet documents
Configuration information for use with the web app API.
Note these values should not be changed unless you are using your own web app API
Object
:
{apkey: (string) key for web app API, apibase: (string) base URL for web app API}
var info = simpleSheetsAPI.apiInfo();
// info.apikey = 'simpleSheetAPI'
// info.apibase = 'https://script.google.com/macros/s/AKfycbyuX2ejECoEhRBp4Dqa8ncr032sW00SLmQAh0DdaT0XEYJrZh4/exec'
retrieve data from all sheets in the Google Sheet document with the given ID (asynchronous)
(string)
the ID for the Google Sheet
Object
:
{success: boolean, data: see
apiReturnData
}
// retrieve data from all sheets in sample data doc
var result = await simpleSheetsAPI.getAllSheetData('1NVd3tAgHhPZ5PZFN2A2h26mPoS2fPDk_aMVEnzCkE74');
// result.success = true if call succeeded
// result.data = object of type apiReturnData if success, otherwise null
// result.details - string describing result, contains an error message if success is false
retrieve data from the specified sheet in the Google Sheet document with the given ID (asynchronous)
(string)
the ID for the Google Sheet
(string)
name of a sheet in the spreadsheet doc
Object
:
{success: boolean, data: see
apiReturnData
}
// retrieve data from "basic" sheet in sample data doc
var result = await simpleSheetsAPI.getSheetData('1NVd3tAgHhPZ5PZFN2A2h26mPoS2fPDk_aMVEnzCkE74', 'basic');
// result.success - true if call succeeded
// result.data - object of type apiReturnData if success, otherwise null
// result.details - string describing result, contains an error message if success is false
spreadsheet data returned from successful API call
Type: Object
(string)
: name of Google Sheet document
(string)
: Google Sheet ID
(Array<string>)
: array of sheet name(s) in document, only one element for getSheetData calls
(Object)
: an object where each key represents a
sheet in the document. Each key value is
a 2D array holding the sheet's data
{
"docname":"test sheet",
"docid":"1NVd3tAgHhPZ5PZFN2A2h26mPoS2fPDk_aMVEnzCkE74",
"sheetnames":["basic"],
"sheetdata":{"basic":[["this is A1","this is B1"],["this is A2","this is B2"]]}}
}
retrieve data as from the specified sheet in the Google Sheet document with the given ID (asynchronous). This differs from getSheetData as the data is packaged into an array of objects with object keys defined by a row from the spreadsheet.
(string)
the ID for the Google Sheet
(string)
name of a sheet in the spreadsheet doc
(integer)
row number (0 based) of header names in spreadsheet data
(integer)
row number (0 based) of the beginning of the content data.
Array<Object>
:
result - array of objects where each fieldname is from the header row
// retrieve sample FAFSA data
fafsaData = await simpleSheetsAPI.getSheetDataAsObjectArray('1PEPzC9eNODx5IX6R7pJmWSk74rYbVkpx8Q3m_j7Ielk', FAFSA, 2, 3);
// result - [ {school: "ALASKA MIDDLE COLLEGE SCHOOL", city: "ANCHORAGE", state: "AK", completed: 23}, ...]
general purpose class for interacting with Google web app APIs
send GET request to web app API (asynchronous)
(Object)
{apikey: {string}, apibase: {string} - base URL for web app API}
(string)
name of GET request
(Object)
query parameters
(Object?)
(optional) object with "reportError" callback for error reporting
Object
:
{success: (boolean), data: (Object)}
// use the simpleSheetAPI to request the data from the "basic" sheet in the sample Google document
var requestResult = await googleWebAppAPI.webAppGet(
{
apikey: 'simpleSheetAPI',
apibase: 'https://script.google.com/macros/s/AKfycbyuX2ejECoEhRBp4Dqa8ncr032sW00SLmQAh0DdaT0XEYJrZh4/exec'
},
'getsheetdata',
{
spreadsheetid: '1NVd3tAgHhPZ5PZFN2A2h26mPoS2fPDk_aMVEnzCkE74',
sheetname: 'basic'
}
);
send POST request to web app API (asynchronous)
(Object)
{apikey: {string}, apibase: {string} - base URL for web app API}
(string)
name of PUT request
(Object)
data to be posted
(Object?)
(optional) object with "reportError" callback for error reporting
Object
:
{success: (boolean), data: (Object)}


| Table 1 |
Average short-run effects of information on beliefs about cl ... |
| Table 2 |
Average short-run effects of information on policy actions. |
| Table 3 |
Short-run effects of information by ideology. |
| Table 4 |
Short-run effects of information by education. |
| Table 5 |
Short-run effects of information by knowledge. |
| Table 6 |
Average long-run effects of information on beliefs about cli ... |
| Table 7 |
Average long-run effects of information on policy actions. |


My Life to a Teacher's
☰ Menu
I wake up at seven
a teacher by dawn
I prepare for only four classes
But they, for the entire day long.
With an early start to the day
Teaching as I speak
They don't get enough rest
But I find them to be a freak.
By the end of my classes
I sit around and play
But a teacher is still not free
All her time is taken away.
By two o'clock of noon
Time for me to have my lunch
But as we all know
For a teacher it's still brunch
I lay down on my bed
As if I am a stack of hay
Feeling tired and lazy
Just as any other day.
But for a teacher
It is not done yet
They don't even have time
For a little breath.
As the night comes up
It's time for all to relax
But for them ,they have to work
As if they are a woodcutter's axe.
Himank Jain
Writer
Philomath team


 "All About Dat Beard"! Subscribe for more Marty Ray Project: http://bit.ly/1ck...
[dscrdeql] <MySoulisNotForSale> fake beards
[dscrdeql] <CowboyCrypto- Founder> some of em are
[dscrdeql] <CowboyCrypto- Founder> lol thats one of my buddies singing it though
[dscrdeql] <MySoulisNotForSale> let me guess, the one with the real beard is your buddy


Unconquered Services is dedicated to empowering young professionals by creating opportunities for them to use their talents that best serve the needs of our community. Pride, Discipline, and Respect define us and the work that we do. Unconquered Services strives to provide the highest quality services available.
What we do.
Residential Cleaning
...
Commercial Cleaning
...
Concierge Services
...
House Soft Wash
...
Concrete / Patio Wash
...
Other
...
About
Unconquered Services was the product of three, hardworking, young men who crossed paths in the Jim Moran College of Entrepreneurship. Jared, Jon, and Will had varying backgrounds in the service industry, and it was the combining of these skills that would then provide the Tallahassee community as Unconquered Services.
Unconquered Services is licensed, bonded, and insured. All of our team members are thoroughly trained and background checked.
Ready to book? Fill out the 'Contact Us' form below, and tell us a little bit about the service needed.
Unconquered Team
Jared Lawrence
Chief Executive Officer
Jonathan Virga
Chief Marketing & Technology Officer
William McCarthy
Chief Operations Officer
Contact Us
(850)800-7139
<EMAIL_ADDRESS>{% crispy form form.helper %}
Residential Cleaning
.

Too busy working all day and cooking all night to find time to vacuum the entire place?
Do you have guests coming over and want to WOW them with how clean your house/apartment looks?
Planning to throw a party and don’t want to worry about cleaning up after Chad’s or Brad’s nasty mess?
Whatever the reason you’re looking for cleaning, we are at your service!
Drop the Mop!
We know you want a reliable, high-quality cleaner that pays attention to detail and never leaves a job unfinished. We offer you a labor pool of young, trained professionals that are not only willing to put in some extra elbow grease, but who also have a positive and respectful attitude while doing it. Get to know them, they’d love to chat with you.
(when they’re not working of course!)
We also understand that you have your specific cleaning needs and preferences, which is why when you book with us we will send you a customizable checklist to ensure we are on the same page. If you have a unique need that is not on the customizable checklist, please let us know and we are happy to work with you!
Set Up a Cleaning Plan
Choose a weekly, biweekly, or monthly cleaning plan. We schedule your recurring bookings to make things easy - but don’t worry, you can always reschedule if things change. Sit back, and relax.
An experienced, fully-equipped housekeeping professional will be there on time.
Move-In/Move-Out Services
Moving out can be stressful, and the last thing you want to worry about is cleaning. Whether you’re a student renting a home or apartment, or you’re a landlord that wants to get a tenant in the property quickly, we will make the space look clean - profesisonally clean.
We offer a comprehensive cleaning service that will allow you to focus on what matters most. Our trained crew goes above and beyond other cleaning companies by leaving no spot of your home or apartment untouched. We will a checklist, which you can customize to fit your preferences, or if your property manager or realtor has provided you with another list, we can follow that precisely!
Unconquered Services is licensed, bonded and insured. We only work with vetted and background checked cleaners.
You will pay a flat rate based on the square footage, number of bedrooms/bathrooms, and the level of cleaning that is necessary.
If you’re not satisfied, we’re not satisfied.
We hope everything we do meets and exceeds your expectations. If you are not 100% satisfied with our services we will refund you. On top of that, we are eager to conquer any competition with a better value for you, so we will match any competitor's prices guaranteed. Email us with a current billing statement or recently dated quote & we will match it guaranteed!
Green Cleaning
We care deeply about the environment and hope you do too, which is why we offer this service with every cleaning we do.
Environmentally friendly & special request cleaning products are available. If you have personal needs or special requests, please let us know.
We are 100% willing to work with you! Feel free to inform us if you require special cleaners, a specific brand, or fragrance that you must have.
Commercial Cleaning
Focus on what matters most.
Increase your employee’s productivity while maintaining a healthy and clean environment.
Unconquered Services brings superior commercial cleaning services to local office buildings, restaurants, lobbies, public bathrooms, and any commercial or retail business properties. Our Commercial Cleaning services will have your property looking as good as new, so that you can focus on what’s most important to you. We offer a personalized, premium, cleaning service for you to get the best value, quality and customer service. We will always work with you to fit your schedule and cleaning needs.
Save time and money by choosing us.
Our crew is highly trained, bonded and insured. We are committed to the welfare and success of you and your facility. Our standard services include:
* Green Cleaning
* General property cleaning – including offices, lobbies, and common areas
* Wipe down office furniture, light fixtures, picture frames, blinds, molding and baseboards.
* Disinfect and sanitize telephones, copiers, computers, doorknobs, light switches and more
* Detailed elevator cleaning – including tracks, walls, and switches
* Floor care (Including: Marble, Tile, Terrazzo, Ceramic, Granite, Concrete, Hardwood)
* Interior window cleaning
* Pressure Washing
* Restroom cleaning and disinfecting
* Breakroom cleaning
* Trash disposal and recycling services
Scheduled cleaning & payment for commercial cleaning services has never been easier.
Our commercial cleaners have flexible schedules that allow your commercial cleaning services to run smoothly, day or night. We realize schedules vary depending on the type of facility you manage, and the hours of operation of your business or office. Your cleaning services can be scheduled from one day to seven days a week, and any hour of the day.
Unconquered Services accepts all major credit cards, checks, money orders & cash. Commercial cleaning schedules can be customized to fit all of your requirements.
You and your family’s health is a top priority, but the humid and wet Florida weather turns the exterior of your home into a breeding ground for mold and mildew. If the mold and mildew are not removed through the soft wash process, it starts to seep into your home through windows, vents, doors and many other small openings in the home.
Mold and mildew can have negative health effects such as; allergic reactions, sneezing, rashes, and if you have more severe mold allergies it can cause shortness of breath. If you have asthma, and you were to breathe in the mold spores it could trigger an asthma attack. The elderly, infants, and children are especially prone to being sensitive to mold spores in the air. Unconquered Services cares about the health of the community and doesn't want you or your loved ones to suffer through the unnecessary consequences of living with mold and mildew.
If you are looking into selling your home, power washing can add $10,000 - $15,000 to the sale price of the home, according to the National Association of Realtors.
We utilize the Soft Wash process to provide a deeper and safer clean to your home.
Low Pressure: We use very low pressure to apply a solution that lifts up the dirt and organic debris from the exterior of your home. We then rinse this away with clean water and low pressure. This process is superior to pressure washing as pressure washing only takes off the top layer of dirt, and forces water into the siding, windows, doors. This causes the mold to spread faster due to water being forced in places it can’t drain from. Without the high pressure, there’s no need to worry about your paint prematurely fading or peeling off.
Deep Clean: We use a 100% environmentally-friendly, biodegradable solution that eliminates all of the dirt and organic growth that breaks down the exterior of your home, and makes it look dirty. Instead of just washing it away with traditional pressure washing, we kill the mold spores so it is much more difficult for the mold to regrow, meaning a cleaner home for longer.
Concrete / Patio Wash
If you have dirty, slippery, and deteriorating concrete, we can bring it back to life
The porous nature of concrete allows dirt and moisture to seep into the concrete leaving discoloration and organic growth. Unconquered Services' two-step process will bring back that bright, clean, concrete back. We pull all of the dirt and discoloring elements out using commercial grade equipment. Then we treat it with a solution that seeps deep down into the pores, and kills off all of the organic growth, leaving you with beaming, beautiful concrete.
Why us?
We are the toughest on grime. We clean to the highest industry standards. We are locally owned and operated in Tallahassee. We use eco-friendly cleaning agents.
Our Pressure Washing Services will make your property shine.
Unconquered service is the first person to call when you’re in need of pressure washing. We are professional, on time, and will show your property the respect it deserves.
Other
What else can we do for you?
Unconquered Services has years of combined experience in a wide variety of disciplines. If you have a job or a project that you need help with, give us a call - We would love to help out.


How to create an ELT Job
Prerequisite : In order to create an ELT job, at-least one ELT project needs be present in the workspace. Follow the link to Create an ELT Project.
To Create a job in Hydrograph, users have been provided with options in the File menu and the Tool bar.
Under the File Menu -> New -> Job, creates a new job on the Canvas
Users can use CTRL + J shortcut key to create an ELT job
Users can alternatively click on the Tool bar button to create a new Job.
Below image shows the job creation window
Provide the name of the job and select any folder to save job.


CrimPapers
Articles published on 2 November 2019
On 2 November 2019, 3 new articles were published in 1 journals.
Is There A Protection Order to Prison Pipeline? Gendered Dimensions of Cross-Petitions by Alesha Durfee, Leigh Goodmark
The Social and Emotional Resources Inventory: Further Development of A Comprehensive Self-Report Measure of Protective Factors by Matthew Oberdorfer, Danielle Mohr, Lee A. Rosén
Misperceptions and Motivations of the Female Terrorist: A Psychological Perspective by Brittany M. Wickham, Nicole M. Capezza, Victoria L. Stephenson


JavaScript is disabled or there is no support. Please enable JavaScript or upgrade your browser to improve your experience.


{% extends "_base.html" %} {% block page_name %}fullwidth{% endblock %} {% block css %} {% endblock %} {% block content %}
4 minutes ago Fulano wrote: Here is a message
4 minutes ago
3 minutes ago Fulana wrote: Here is a second message
3 minutes ago
2 minutes ago Fuloni wrote: Here is yet another message
2 minutes ago


Welcome to:Satyam's home.
My email id Gmail
A link to my facebook account.
My favourite website Favourite Website.
A link to my : Github account .
A link to my Quora account.
Worlds search engine.My role model , my mentor < PROGYAN DAA.>
My school Kendriya Vidalaya
A link to video of kv muzaffarpur morning assembly.


Code and slides available at Github: @millenc
Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods.
Unfortunately, our goods are constantly degrading in quality as they approach their sell by date.
We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items.
First an introduction to our system:
Pretty simple, right? Well this is where it gets interesting:
Hold on! We also sell "special" items:
Here's our new requirement! We have recently signed a supplier of conjured items. This requires an update to our system:
Final words:
Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly.
However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you).
class GildedRose(object):
def __init__(self, items):
self.items = items
def update_quality(self):
for item in self.items:
if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert":
if item.quality > 0:
if item.name != "Sulfuras, Hand of Ragnaros":
item.quality = item.quality - 1
else:
if item.quality < 50:
item.quality = item.quality + 1
if item.name == "Backstage passes to a TAFKAL80ETC concert":
if item.sell_in < 11:
if item.quality < 50:
item.quality = item.quality + 1
if item.sell_in < 6:
if item.quality < 50:
item.quality = item.quality + 1
if item.name != "Sulfuras, Hand of Ragnaros":
item.sell_in = item.sell_in - 1
if item.sell_in < 0:
if item.name != "Aged Brie":
if item.name != "Backstage passes to a TAFKAL80ETC concert":
if item.quality > 0:
if item.name != "Sulfuras, Hand of Ragnaros":
item.quality = item.quality - 1
else:
item.quality = item.quality - item.quality
else:
if item.quality < 50:
item.quality = item.quality + 1
class Item:
def __init__(self, name, sell_in, quality):
self.name = name
self.sell_in = sell_in
self.quality = quality
def __repr__(self):
return "%s, %s, %s" % (self.name, self.sell_in, self.quality)
test_gilded_rose.py:
# -*- coding: utf-8 -*-
import unittest
from gilded_rose import Item, GildedRose
class GildedRoseTest(unittest.TestCase):
def test_foo(self):
items = [Item("foo", 0, 0)]
gilded_rose = GildedRose(items)
gilded_rose.update_quality()
self.assertEquals("fixme", items[0].name)
if __name__ == '__main__':
unittest.main()
The update_quality() method is a complete mess of spaghetti code!
item.quality = item.quality - item.quality
We are going to refactor this code and add the new requirement using the following approach:
Add unit tests to the test_gilded_rose.py file. Here, we've created an _update_item() auxiliary function that takes an item, updates it and returns it back.
This will make writing tests very straight-forward:
# -*- coding: utf-8 -*-
import unittest
from gilded_rose import Item, GildedRose
class GildedRoseTest(unittest.TestCase):
def _update_item(self, item):
GildedRose([item]).update_quality()
return item
One test per business rule:
def test_quality_degrades(self):
self.assertEquals(self._update_item(Item("Elixir of the Mongoose", 10, 50)).quality, 49)
def test_sell_in_decrements(self):
self.assertEquals(self._update_item(Item("Elixir of the Mongoose", 10, 50)).sell_in, 9)
def test_quality_degrades_twice_as_fast_when_sell_in_passed(self):
self.assertEquals(self._update_item(Item("Elixir of the Mongoose", 0, 50)).quality, 48)
def test_quality_higher_or_equal_zero(self):
self.assertEquals(self._update_item(Item("Elixir of the Mongoose", 0, 0)).quality, 0)
def test_quality_less_or_equal_fifty(self):
self.assertEquals(self._update_item(Item("Aged Brie", 10, 50)).quality, 50)
def test_aged_brie_quality_increases(self):
self.assertEquals(self._update_item(Item("Aged Brie", 10, 40)).quality, 41)
def test_sulfuras_inmutable(self):
sulfuras = Item("Sulfuras, Hand of Ragnaros", 10, 80)
self.assertEquals(self._update_item(sulfuras).quality, 80)
self.assertEquals(self._update_item(sulfuras).sell_in, 10)
def test_backstage_passes_quality_increases(self):
self.assertEquals(self._update_item(Item("Backstage passes to a TAFKAL80ETC concert", 15, 40)).quality, 41)
def test_backstage_passes_quality_increases_when_sell_in_ten_days_or_less(self):
self.assertEquals(self._update_item(Item("Backstage passes to a TAFKAL80ETC concert", 10, 40)).quality, 42)
def test_backstage_passes_quality_increases_when_sell_in_five_days_or_less(self):
self.assertEquals(self._update_item(Item("Backstage passes to a TAFKAL80ETC concert", 5, 40)).quality, 43)
def test_backstage_passes_quality_drops_to_zero_when_sell_in_passed(self):
self.assertEquals(self._update_item(Item("Backstage passes to a TAFKAL80ETC concert", 0, 40)).quality, 0)
Enough talk! Show me the code!
class GildedRose(object):
def __init__(self, items):
self.items = items
def update_quality(self):
for item in self.items:
if item.name == "Aged Brie":
self.update_aged_brie_item_quality(item)
elif item.name == "Sulfuras, Hand of Ragnaros":
self.update_sulfuras_item_quality(item)
elif item.name == "Backstage passes to a TAFKAL80ETC concert":
self.update_backstage_pass_item_quality(item)
else:
self.update_item_quality(item)
def update_item_sell_in(self, item):
item.sell_in -= 1
def update_item_quality(self, item):
self.update_item_sell_in(item)
item.quality = max(0, item.quality - (1 if item.sell_in >= 0 else 2))
def update_aged_brie_item_quality(self, item):
self.update_item_sell_in(item)
item.quality = min(50, item.quality + 1)
def update_sulfuras_item_quality(self, item):
pass
def update_backstage_pass_item_quality(self, item):
self.update_item_sell_in(item)
item.quality = 0 if item.sell_in < 0 else min(50, item.quality + 1 + (1 if item.sell_in < 11 else 0)
+ (1 if item.sell_in < 6 else 0))
This refactored code passes all the tests! With this refactor we've achieved:
With this simple first refactor we can easily add the new requirement for Conjured items. We just have to modify the update_item_quality() function:
def update_item_quality(self, item):
self.update_item_sell_in(item)
item.quality = max(0, item.quality - (1 if item.sell_in >= 0 else 2) * (2 if item.name.startswith("Conjured") else 1))
And some tests:
def test_conjured_quality_degrades(self):
self.assertEquals(self._update_item(Item("Conjured Elixir of the Mongoose", 10, 50)).quality, 48)
def test_conjured_quality_degrades_twice_as_fast_when_sell_in_passed(self):
self.assertEquals(self._update_item(Item("Conjured Elixir of the Mongoose", 0, 50)).quality, 46)
While this refactor is a net improvement over the original code, it still has important flaws:
Time for a new refactor!
The goal of this refactor is extracting all the logic for updating each category of items in a way that it can be re-used and easily extended:
For that, we are going to use the Strategy Design Pattern:
We are going to create classes that encapsulate the update quality logic for each category of items.


This Website
My second project for Udacity's Full Stack Nanodegree. The content on this website is responsive at just about every viewport width (Go ahead and resize the window and watch that sweet sweet responsiveness.) and was developed "mobile first."
The project tasked me with using all my new HTML and CSS powers to turn a design
mockup into a web page. I had many difficult ridiculous amazing ideas and
changes I wanted to make to the mockup. Lucky for me step 4 leaves
room (At least I hope my project reviewer thinks so...) to personalize and add additional
content to my portfolio.
I spent quite a bit of time building this humble little web page. I spent a few weeks just learning Affinity Designer and brainstorming a site logo until deciding on the one at the top right of this page.
Other tools used to create this site:
- HTML
- CSS
- PostCSS
- Javascript
- Gulp
- Firebase
- Udacity FSND


--- title: 'Proofs without Words using gganimate' author: 'Notesofdabbler' date: '2020-04-26' slug: 'proofnowords' comments: true categories: ["R"] tags: ["R"] ---
I recently watched the 2 part workshop (part 1, part 2) on ggplot2 and extensions given by Thomas Lin Pedersen. First of, it was really nice of Thomas to give the close to 4 hour workshop for the benefit of the community. I personally learnt a lot from it. I wanted to try out gganimate extension that was covered during the workshop.
There are several resources on the web that show animations/illustrations of proofs of mathematical identities and theorems without words (or close to it). I wanted to take a few of those examples and use gganimate to recreate the illustration. This was a fun way for me to try out gganimate.
This example is taken from AoPS Online and the result is that sum of first \(n\) odd numbers equals \(n^2\). \[ 1 + 3 + 5 + \ldots + (2n - 1) = n^2 \] The gganimate version of the proof (using the method in AoPS Online) is shown below (R code, html file)
This example is also taken from AoPS Online and the result is:
\[ 1^3 + 2^3 + \ldots + (n-1)^3 + n^3 = (1 + 2 + \ldots + n)^2 \] The gganimate version of the proof (using the method in AoPS Online) is shown below ( R code, html file):
This example from AoPS Online illustrates the result
\[ \frac{1}{2^2} + \frac{1}{2^4} + \frac{1}{2^6} + \frac{1}{2^8} + \ldots = \frac{1}{3} \] The gganimate version of the proof (using the method in AoPS Online) is shown below ( R code, html file):
According to Pythagoras theorem, \[ a^2 + b^2 = c^2 \] where \(a\), \(b\), \(c\) are sides of a right angled triangle (with \(c\) being the side opposite \(90^o\) angle)
There was an illustration of the proof of pythogoras theorem in a video from echalk.
The gganimate version of the proof is shown below ( R code, html file)
In summary, it was great to use gganimate for these animations since it does all the magic with making transitions work nicely.
{{% disqus %}}


About Me:
Hi, my name is Graicen Radel. Welcome to my Digital Fabricaction page for uploading projects. I am currently a junior at Western Reserve Academy and a day student from Twinsburg. I love to create things and I am excited to learn new things!
Index


{% import "../../new/topbar.html" as topbar%} {% import "../../new/topnav.html" as topnav%} {% import "./doc-nav.html" as docnav %}