For potential users coming from Stata this page is meant to demonstrate how different Stata operations would be performed in pandas.
If you’re new to pandas, you might want to first read through 10 Minutes to pandas to familiarize yourself with the library.
As is customary, we import pandas and NumPy as follows. This means that we can refer to the libraries as pd and np, respectively, for the rest of the document.
pd
np
In [1]: import pandas as pd In [2]: import numpy as np
Note
Throughout this tutorial, the pandas DataFrame will be displayed by calling df.head(), which displays the first N (default 5) rows of the DataFrame. This is often used in interactive work (e.g. Jupyter notebook or terminal) – the equivalent in Stata would be:
DataFrame
df.head()
list in 1/5
pandas
Stata
data set
column
variable
row
observation
groupby
bysort
NaN
.
Series
A DataFrame in pandas is analogous to a Stata data set – a two-dimensional data source with labeled columns that can be of different types. As will be shown in this document, almost any operation that can be applied to a data set in Stata can also be accomplished in pandas.
A Series is the data structure that represents one column of a DataFrame. Stata doesn’t have a separate data structure for a single column, but in general, working with a Series is analogous to referencing a column of a data set in Stata.
Index
Every DataFrame and Series has an Index – labels on the rows of the data. Stata does not have an exactly analogous concept. In Stata, a data set’s rows are essentially unlabeled, other than an implicit integer index that can be accessed with _n.
_n
In pandas, if no index is specified, an integer index is also used by default (first row = 0, second row = 1, and so on). While using a labeled Index or MultiIndex can enable sophisticated analyses and is ultimately an important part of pandas to understand, for this comparison we will essentially ignore the Index and just treat the DataFrame as a collection of columns. Please see the indexing documentation for much more on how to use an Index effectively.
MultiIndex
A Stata data set can be built from specified values by placing the data after an input statement and specifying the column names.
input
input x y 1 2 3 4 5 6 end
A pandas DataFrame can be constructed in many different ways, but for a small number of values, it is often convenient to specify it as a Python dictionary, where the keys are the column names and the values are the data.
In [3]: df = pd.DataFrame({'x': [1, 3, 5], 'y': [2, 4, 6]}) In [4]: df Out[4]: x y 0 1 2 1 3 4 2 5 6
Like Stata, pandas provides utilities for reading in data from many formats. The tips data set, found within the pandas tests (csv) will be used in many of the following examples.
tips
Stata provides import delimited to read csv data into a data set in memory. If the tips.csv file is in the current working directory, we can import it as follows.
import delimited
tips.csv
import delimited tips.csv
The pandas method is read_csv(), which works similarly. Additionally, it will automatically download the data set if presented with a url.
read_csv()
In [5]: url = ('https://raw.github.com/pandas-dev' ...: '/pandas/master/pandas/tests/data/tips.csv') ...: In [6]: tips = pd.read_csv(url) In [7]: tips.head() Out[7]: total_bill tip sex smoker day time size 0 16.99 1.01 Female No Sun Dinner 2 1 10.34 1.66 Male No Sun Dinner 3 2 21.01 3.50 Male No Sun Dinner 3 3 23.68 3.31 Male No Sun Dinner 2 4 24.59 3.61 Female No Sun Dinner 4
Like import delimited, read_csv() can take a number of parameters to specify how the data should be parsed. For example, if the data were instead tab delimited, did not have column names, and existed in the current working directory, the pandas command would be:
tips = pd.read_csv('tips.csv', sep='\t', header=None) # alternatively, read_table is an alias to read_csv with tab delimiter tips = pd.read_table('tips.csv', header=None)
Pandas can also read Stata data sets in .dta format with the read_stata() function.
.dta
read_stata()
df = pd.read_stata('data.dta')
In addition to text/csv and Stata files, pandas supports a variety of other data formats such as Excel, SAS, HDF5, Parquet, and SQL databases. These are all read via a pd.read_* function. See the IO documentation for more details.
pd.read_*
The inverse of import delimited in Stata is export delimited
export delimited
export delimited tips2.csv
Similarly in pandas, the opposite of read_csv is DataFrame.to_csv().
read_csv
DataFrame.to_csv()
tips.to_csv('tips2.csv')
Pandas can also export to Stata file format with the DataFrame.to_stata() method.
DataFrame.to_stata()
tips.to_stata('tips2.dta')
In Stata, arbitrary math expressions can be used with the generate and replace commands on new or existing columns. The drop command drops the column from the data set.
generate
replace
drop
replace total_bill = total_bill - 2 generate new_bill = total_bill / 2 drop new_bill
pandas provides similar vectorized operations by specifying the individual Series in the DataFrame. New columns can be assigned in the same way. The DataFrame.drop() method drops a column from the DataFrame.
DataFrame.drop()
In [8]: tips['total_bill'] = tips['total_bill'] - 2 In [9]: tips['new_bill'] = tips['total_bill'] / 2 In [10]: tips.head() Out[10]: total_bill tip sex smoker day time size new_bill 0 14.99 1.01 Female No Sun Dinner 2 7.495 1 8.34 1.66 Male No Sun Dinner 3 4.170 2 19.01 3.50 Male No Sun Dinner 3 9.505 3 21.68 3.31 Male No Sun Dinner 2 10.840 4 22.59 3.61 Female No Sun Dinner 4 11.295 In [11]: tips = tips.drop('new_bill', axis=1)
Filtering in Stata is done with an if clause on one or more columns.
if
list if total_bill > 10
DataFrames can be filtered in multiple ways; the most intuitive of which is using boolean indexing.
In [12]: tips[tips['total_bill'] > 10].head() Out[12]: total_bill tip sex smoker day time size 0 14.99 1.01 Female No Sun Dinner 2 2 19.01 3.50 Male No Sun Dinner 3 3 21.68 3.31 Male No Sun Dinner 2 4 22.59 3.61 Female No Sun Dinner 4 5 23.29 4.71 Male No Sun Dinner 4
In Stata, an if clause can also be used to create new columns.
generate bucket = "low" if total_bill < 10 replace bucket = "high" if total_bill >= 10
The same operation in pandas can be accomplished using the where method from numpy.
where
numpy
In [13]: tips['bucket'] = np.where(tips['total_bill'] < 10, 'low', 'high') In [14]: tips.head() Out[14]: total_bill tip sex smoker day time size bucket 0 14.99 1.01 Female No Sun Dinner 2 high 1 8.34 1.66 Male No Sun Dinner 3 low 2 19.01 3.50 Male No Sun Dinner 3 high 3 21.68 3.31 Male No Sun Dinner 2 high 4 22.59 3.61 Female No Sun Dinner 4 high
Stata provides a variety of functions to do operations on date/datetime columns.
generate date1 = mdy(1, 15, 2013) generate date2 = date("Feb152015", "MDY") generate date1_year = year(date1) generate date2_month = month(date2) * shift date to beginning of next month generate date1_next = mdy(month(date1) + 1, 1, year(date1)) if month(date1) != 12 replace date1_next = mdy(1, 1, year(date1) + 1) if month(date1) == 12 generate months_between = mofd(date2) - mofd(date1) list date1 date2 date1_year date2_month date1_next months_between
The equivalent pandas operations are shown below. In addition to these functions, pandas supports other Time Series features not available in Stata (such as time zone handling and custom offsets) – see the timeseries documentation for more details.
In [15]: tips['date1'] = pd.Timestamp('2013-01-15') In [16]: tips['date2'] = pd.Timestamp('2015-02-15') In [17]: tips['date1_year'] = tips['date1'].dt.year In [18]: tips['date2_month'] = tips['date2'].dt.month In [19]: tips['date1_next'] = tips['date1'] + pd.offsets.MonthBegin() In [20]: tips['months_between'] = (tips['date2'].dt.to_period('M') ....: - tips['date1'].dt.to_period('M')) ....: In [21]: tips[['date1', 'date2', 'date1_year', 'date2_month', 'date1_next', ....: 'months_between']].head() ....:  Note that in contrast to Stata, these operations do not happen in place. To make these changes persist, assign the operation back to a variable.
# keep In [22]: tips[['sex', 'total_bill', 'tip']].head() Out[22]: sex total_bill tip 0 Female 14.99 1.01 1 Male 8.34 1.66 2 Male 19.01 3.50 3 Male 21.68 3.31 4 Female 22.59 3.61 # drop In [23]: tips.drop('sex', axis=1).head() Out[23]: total_bill tip smoker day time size 0 14.99 1.01 No Sun Dinner 2 1 8.34 1.66 No Sun Dinner 3 2 19.01 3.50 No Sun Dinner 3 3 21.68 3.31 No Sun Dinner 2 4 22.59 3.61 No Sun Dinner 4 # rename In [24]: tips.rename(columns={'total_bill': 'total_bill_2'}).head() Out[24]: total_bill_2 tip sex smoker day time size 0 14.99 1.01 Female No Sun Dinner 2 1 8.34 1.66 Male No Sun Dinner 3 2 19.01 3.50 Male No Sun Dinner 3 3 21.68 3.31 Male No Sun Dinner 2 4 22.59 3.61 Female No Sun Dinner 4
Sorting in Stata is accomplished via sort
sort
sort sex total_bill
pandas objects have a DataFrame.sort_values() method, which takes a list of columns to sort by.
DataFrame.sort_values()
In [25]: tips = tips.sort_values(['sex', 'total_bill']) In [26]: tips.head() Out[26]: total_bill tip sex smoker day time size 67 1.07 1.00 Female Yes Sat Dinner 1 92 3.75 1.00 Female Yes Fri Dinner 2 111 5.25 1.00 Female No Sat Dinner 1 145 6.35 1.50 Female No Thur Lunch 2 135 6.51 1.25 Female No Thur Lunch 2
Stata determines the length of a character string with the strlen() and ustrlen() functions for ASCII and Unicode strings, respectively.
strlen()
ustrlen()
generate strlen_time = strlen(time) generate ustrlen_time = ustrlen(time)
Python determines the length of a character string with the len function. In Python 3, all strings are Unicode strings. len includes trailing blanks. Use len and rstrip to exclude trailing blanks.
len
rstrip
In [27]: tips['time'].str.len().head() Out[27]: 67 6 92 6 111 6 145 5 135 5 Name: time, dtype: int64 In [28]: tips['time'].str.rstrip().str.len().head() Out[28]: 67 6 92 6 111 6 145 5 135 5 Name: time, dtype: int64
Stata determines the position of a character in a string with the strpos() function. This takes the string defined by the first argument and searches for the first position of the substring you supply as the second argument.
strpos()
generate str_position = strpos(sex, "ale")
Python determines the position of a character in a string with the find() function. find searches for the first position of the substring. If the substring is found, the function returns its position. Keep in mind that Python indexes are zero-based and the function will return -1 if it fails to find the substring.
find()
find
In [29]: tips['sex'].str.find("ale").head() Out[29]: 67 3 92 3 111 3 145 3 135 3 Name: sex, dtype: int64
Stata extracts a substring from a string based on its position with the substr() function.
substr()
generate short_sex = substr(sex, 1, 1)
With pandas you can use [] notation to extract a substring from a string by position locations. Keep in mind that Python indexes are zero-based.
 The first argument is the string you want to parse and the second argument specifies which word you want to extract.
word()
clear input str20 string "John Smith" "Jane Cook" end generate first_name = word(name, 1) generate last_name = word(name, -1)
Python extracts a substring from a string based on its text by using regular expressions. There are much more powerful approaches, but this just shows a simple approach.
In [31]: firstlast = pd.DataFrame({'string': ['John Smith', 'Jane Cook']}) In [32]: firstlast['First_Name'] = firstlast['string'].str.split(" ", expand=True)[0] In [33]: firstlast['Last_Name'] = firstlast['string'].str.rsplit(" ", expand=True)[0] In [34]: firstlast Out[34]: string First_Name Last_Name 0 John Smith John John 1 Jane Cook Jane Jane
The Stata strupper(), strlower(), strproper(), ustrupper(), ustrlower(), and ustrtitle() functions change the case of ASCII and Unicode strings, respectively.
strupper()
strlower()
strproper()
ustrupper()
ustrlower()
ustrtitle()
clear input str20 string "John Smith" "Jane Cook" end generate upper = strupper(string) generate lower = strlower(string) generate title = strproper(string) list
The equivalent Python functions are upper, lower, and title.
upper
lower
title
In [35]: firstlast = pd.DataFrame({'string': ['John Smith', 'Jane Cook']}) In [36]: firstlast['upper'] = firstlast['string'].str.upper() In [37]: firstlast['lower'] = firstlast['string'].str.lower() In [38]: firstlast['title'] = firstlast['string'].str.title() In [39]: firstlast Out[39]: string upper lower title 0 John Smith JOHN SMITH john smith John Smith 1 Jane Cook JANE COOK jane cook Jane Cook
The following tables will be used in the merge examples
In [40]: df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], ....: 'value': np.random.randn(4)}) ....: In [41]: df1 Out[41]: key value 0 A 0.469112 1 B -0.282863 2 C -1.509059 3 D -1.135632 In [42]: df2 = pd.DataFrame({'key': ['B', 'D', 'D', 'E'], ....: 'value': np.random.randn(4)}) ....: In [43]: df2 Out[43]: key value 0 B 1.212112 1 D -0.173215 2 D 0.119209 3 E -1.044236
In Stata, to perform a merge, one data set must be in memory and the other must be referenced as a file name on disk. In contrast, Python must have both DataFrames already in memory.
DataFrames
By default, Stata performs an outer join, where all observations from both data sets are left in memory after the merge. One can keep only observations from the initial data set, the merged data set, or the intersection of the two by using the values created in the _merge variable.
_merge
* First create df2 and save to disk clear input str1 key B D D E end generate value = rnormal() save df2.dta * Now create df1 in memory clear input str1 key A B C D end generate value = rnormal() preserve * Left join merge 1:n key using df2.dta keep if _merge == 1 * Right join restore, preserve merge 1:n key using df2.dta keep if _merge == 2 * Inner join restore, preserve merge 1:n key using df2.dta keep if _merge == 3 * Outer join restore merge 1:n key using df2.dta
pandas DataFrames have a DataFrame.merge() method, which provides similar functionality. Note that different join types are accomplished via the how keyword.
DataFrame.merge()
how
In [44]: inner_join = df1.merge(df2, on=['key'], how='inner') In [45]: inner_join Out[45]: key value_x value_y 0 B -0.282863 1.212112 1 D -1.135632 -0.173215 2 D -1.135632 0.119209 In [46]: left_join = df1.merge(df2, on=['key'], how='left') In [47]: left_join Out[47]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 NaN 3 D -1.135632 -0.173215 4 D -1.135632 0.119209 In [48]: right_join = df1.merge(df2, on=['key'], how='right') In [49]: right_join Out[49]: key value_x value_y 0 B -0.282863 1.212112 1 D -1.135632 -0.173215 2 D -1.135632 0.119209 3 E NaN -1.044236 In [50]: outer_join = df1.merge(df2, on=['key'], how='outer') In [51]: outer_join Out[51]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 NaN 3 D -1.135632 -0.173215 4 D -1.135632 0.119209 5 E NaN -1.044236
Like Stata, pandas has a representation for missing data – the special float value NaN (not a number). Many of the semantics are the same; for example missing data propagates through numeric operations, and is ignored by default for aggregations.
In [52]: outer_join Out[52]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 NaN 3 D -1.135632 -0.173215 4 D -1.135632 0.119209 5 E NaN -1.044236 In [53]: outer_join['value_x'] + outer_join['value_y'] Out[53]: 0 NaN 1 0.929249 2 NaN 3 -1.308847 4 -1.016424 5 NaN dtype: float64 In [54]: outer_join['value_x'].sum() Out[54]: -3.5940742896293765
One difference is that missing data cannot be compared to its sentinel value. For example, in Stata you could do this to filter missing values.
* Keep missing values list if value_x == . * Keep non-missing values list if value_x != .
This doesn’t work in pandas. Instead, the pd.isna() or pd.notna() functions should be used for comparisons.
pd.isna()
pd.notna()
In [55]: outer_join[pd.isna(outer_join['value_x'])] Out[55]: key value_x value_y 5 E NaN -1.044236 In [56]: outer_join[pd.notna(outer_join['value_x'])] Out[56]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 NaN 3 D -1.135632 -0.173215 4 D -1.135632 0.119209
Pandas also provides a variety of methods to work with missing data – some of which would be challenging to express in Stata. For example, there are methods to drop all rows with any missing values, replacing missing values with a specified value, like the mean, or forward filling from previous rows. See the missing data documentation for more.
# Drop rows with any missing value In [57]: outer_join.dropna() Out[57]: key value_x value_y 1 B -0.282863 1.212112 3 D -1.135632 -0.173215 4 D -1.135632 0.119209 # Fill forwards In [58]: outer_join.fillna(method='ffill') Out[58]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 1.212112 3 D -1.135632 -0.173215 4 D -1.135632 0.119209 5 E -1.135632 -1.044236 # Impute missing values with the mean In [59]: outer_join['value_x'].fillna(outer_join['value_x'].mean()) Out[59]: 0 0.469112 1 -0.282863 2 -1.509059 3 -1.135632 4 -1.135632 5 -0.718815 Name: value_x, dtype: float64
Stata’s collapse can be used to group by one or more key variables and compute aggregations on numeric columns.
collapse
collapse (sum) total_bill tip, by(sex smoker)
pandas provides a flexible groupby mechanism that allows similar aggregations. See the groupby documentation for more details and examples.
In [60]: tips_summed = tips.groupby(['sex', 'smoker'])[['total_bill', 'tip']].sum() In [61]: tips_summed.head() Out[61]: total_bill tip sex smoker Female No 869.68 149.77 Yes 527.27 96.74 Male No 1725.75 302.00 Yes 1217.07 183.07
In Stata, if the group aggregations need to be used with the original data set, one would usually use bysort with egen(). For example, to subtract the mean for each observation by smoker group.
egen()
bysort sex smoker: egen group_bill = mean(total_bill) generate adj_total_bill = total_bill - group_bill
pandas groupby provides a transform mechanism that allows these type of operations to be succinctly expressed in one operation.
transform
In [62]: gb = tips.groupby('smoker')['total_bill'] In [63]: tips['adj_total_bill'] = tips['total_bill'] - gb.transform('mean') In [64]: tips.head() Out[64]: total_bill tip sex smoker day time size adj_total_bill 67 1.07 1.00 Female Yes Sat Dinner 1 -17.686344 92 3.75 1.00 Female Yes Fri Dinner 2 -15.006344 111 5.25 1.00 Female No Sat Dinner 1 -11.938278 145 6.35 1.50 Female No Thur Lunch 2 -10.838278 135 6.51 1.25 Female No Thur Lunch 2 -10.678278
In addition to aggregation, pandas groupby can be used to replicate most other bysort processing from Stata. For example, the following example lists the first observation in the current sort order by sex/smoker group.
bysort sex smoker: list if _n == 1
In pandas this would be written as:
In [65]: tips.groupby(['sex', 'smoker']).first() Out[65]: total_bill tip day time size adj_total_bill sex smoker Female No 5.25 1.00 Sat Dinner 1 -11.938278 Yes 1.07 1.00 Sat Dinner 1 -17.686344 Male No 5.51 2.00 Thur Lunch 2 -11.678278 Yes 5.25 5.15 Sun Dinner 2 -13.506344
Pandas and Stata both operate exclusively in memory. This means that the size of data able to be loaded in pandas is limited by your machine’s memory. If out of core processing is needed, one possibility is the dask.dataframe library, which provides a subset of pandas functionality for an on-disk DataFrame.


Mad twitter is a highly user friendly button, that produces different animations on hover effect. Six different effects makes the twitter angry and it goes wild, which is the most interesting feature of mad twitter button.
Mad twitter is an easy to use jquery plugin. A css file must be included to make it work properly.
<link href="css/mad_twitter.css" rel="stylesheet" media="all" />

mad_twitter.js
will work perfectly.

Follow us

$("#mad_twitter_1").hover(function(){
$("#mad_twitter_1 .fa-twitter").toggleClass("magictime foolishIn");
});
There are six unique animations and can be chaged as follows;
Insead of using "follishIn" in the above script user can use following animations
Mad Twitter is created by Top Gravity, licensed under MIT and is free to use.


sites selected positively OpenUrl selection HCV-a CrossRef HCV epitopes positive HCV-b Science Web hepatitis virus different obtained subtypes differences genome protein sequences RNA analyses conserved using positions structure viral amino codon distribution evolution number analysis secondary FEL association neutral performed significant similar conservation detected purifying MEME considered dataset higher results structures subtype (Supplementary T-cell acid cell compared evolutionary immune major methods model presence present significantly used variability >; Abstract Cuevas Evol. Martin Table acids associated epitope genetic hypothesis phylogenetic response selection. sequences. site virus. (HCV-a: FREE HCV-b, Hepatitis However, Kosakovsky Material Pond Posada Snoeck Supplementary Text analyzed effects evolving genomes genomes, heterozygosity including level means method mutation nucleotide proportion proteins second sites, size studies tests trees values Bioinformatics Biol Campo Core HCV-a, HCV-b: Hepatol. LRT Mol Murrell NS, Res. Virol. Virus antiviral beta detection estimated external genes genomic genotypes increased infection. information mapped null reported respectively. selective subsets subtype, subtypes. Acids Beta FDR FastTree HCV, HCV-b. Infect Maddison Magiorkinis Nei Nucl Pybus Sanjuán Simmonds Torres-Puente according alpha antibody based changes complete conservation, constraints dN/dS diversity episodic genes. genome. given high human implemented included independent large level. lineages list location lowest map methods. multiple new order population position presented random rate rates reference regions regression role sites. statistical total totally treatment variables variants work


{% extends "horizon/common/_modal_form.html" %} {% load i18n %} {% block modal-body-right %}
{% trans "Specify the details of the instance to be added to the cluster." %}
{% trans "The name field is optional. If the field is left blank a name will be generated when the cluster is grown." %}
{% trans "The 'Instance Type' and 'Related To' fields are datastore specific and optional. See the Trove documentation for more information on using these fields." %}
{% endblock %}


Logout
Welcome....
You are logged in as {{question}}
Questions to solve....
LeaderBoard: :
{{error}}
{% for question in questions %}
{{ question['question'] }}
submit
{% endfor %}


The AECC (Asociación Estudiantil de Ciencia de Cómputos) is an officially recognized student organization at UPR-RP. We are the AECC's 2017-2018 governing board, our purpose and our mission is to fulfill the organization's commitment with bringing quality resources to our members and providing assistence in any way we can. In doing so, we also wish to develop our leadership, social, professional, and academic skills. In this page you can find out more details about each of us, and our individual interests and motivations. Please support us in any way you wish and spread the word!


8 Modules
In Elixir we group several functions into modules. We've already used many different modules in the previous chapters like the String
module:
iex> String.length "hello"
5
In order to create our own modules in Elixir, we use the defmodule
macro. We use the def
macro to define functions in that module:
iex> defmodule Math do
...> def sum(a, b) do
...> a + b
...> end
...> end
iex> Math.sum(1, 2)
3
In the following sections, our examples are going to get a bit more complex, and it can be tricky to type them all in the shell. It's about time for us to learn how to compile Elixir code and also how to run Elixir scripts.
8.1 Compilation
Most of the time it is convenient to write modules into files so they can be compiled and reused. Let's assume we have a file named math.ex
with the following contents:
defmodule Math do
def sum(a, b) do
a + b
end
end
This file can be compiled using elixirc
:
$ elixirc math.ex
This will generate a file named Elixir.Math.beam
containing the bytecode for the defined module. If we start iex
again, our module definition will be available (provided that iex
is started in the same directory the bytecode file is in):
iex> Math.sum(1, 2)
3
Elixir projects are usually organized into three directories:
- ebin - contains the compiled bytecode
- lib - contains elixir code (usually
.ex
files) - test - contains tests (usually
.exs
files)
When working on actual projects, the build tool called mix
will be responsible for compiling and setting up the proper paths for you. For learning purposes, Elixir also supports a scripted mode which is more flexible and does not generate any compiled artifacts.
8.2 Scripted mode
In addition to the Elixir file extension .ex
, Elixir also supports .exs
files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. .ex
files are meant to be compiled while .exs
files are used for scripting, without the need for compilation. For instance, we can create a file called math.exs
:
defmodule Math do
def sum(a, b) do
a + b
end
end
IO.puts Math.sum(1, 2)
And execute it as:
$ elixir math.exs
The file will be compiled in memory and executed, printing "3" as the result. No bytecode file will be created. In the following examples, we recommend you write your code into script files and execute them as shown above.
8.3 Named functions
Inside a module, we can define functions with def/2
and private functions with defp/2
. A function defined with def/2
can be invoked from other modules while a private function can only be invoked locally.
defmodule Math do
def sum(a, b) do
do_sum(a, b)
end
defp do_sum(a, b) do
a + b
end
end
Math.sum(1, 2) #=> 3
Math.do_sum(1, 2) #=> ** (UndefinedFunctionError)
Function declarations also support guards and multiple clauses. If a function has several clauses, Elixir will try each clause until it finds one that matches. Here is an implementation of a function that checks if the given number is zero or not:
defmodule Math do
def zero?(0) do
true
end
def zero?(x) when is_number(x) do
false
end
end
Math.zero?(0) #=> true
Math.zero?(1) #=> false
Math.zero?([1,2,3])
#=> ** (FunctionClauseError)
Giving an argument that does not match any of the clauses raises an error.
8.4 Function capturing
Throughout this tutorial, we have been using the notation name/arity
to refer to functions. It happens that this notation can actually be used to retrieve a named function as a function type. Let's start iex
and run the math.exs
file defined above:
$ iex math.exs
iex> Math.zero?(0)
true
iex> fun = &Math.zero?/1
&Math.zero?/1
iex> is_function fun
true
iex> fun.(0)
true
Local or imported functions, like is_function/1
, can be captured without the module:
iex> &is_function/1
&:erlang.is_function/1
iex> (&is_function/1).(fun)
true
Note the capture syntax can also be used as a shortcut for creating functions:
iex> fun = &(&1 + 1)
#Function<6.71889879/1 in :erl_eval.expr/5>
iex> fun.(1)
2
The &1
represents the first argument passed into the function. &(&1+1)
above is exactly the same as fn x -> x + 1 end
. The syntax above is useful for short function definitions. You can read more about the capture operator &
in the Kernel.SpecialForms
documentation.
8.5 Default arguments
Named functions in Elixir also support default arguments:
defmodule Concat do
def join(a, b, sep \\ " ") do
a <> sep <> b
end
end
IO.puts Concat.join("Hello", "world") #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world
Any expression is allowed to serve as a default value, but it won't be evaluated during the function definition; it will simply be stored for later use. Every time the function is invoked and any of its default values have to be used, the expression for that default value will be evaluated:
defmodule DefaultTest do
def dowork(x \\ IO.puts "hello") do
x
end
end
iex> DefaultTest.dowork
hello
:ok
iex> DefaultTest.dowork 123
123
iex> DefaultTest.dowork
hello
:ok
If a function with default values has multiple clauses, it is recommended to create a function head (without an actual body), just for declaring defaults:
defmodule Concat do
def join(a, b \\ nil, sep \\ " ")
def join(a, b, _sep) when is_nil(b) do
a
end
def join(a, b, sep) do
a <> sep <> b
end
end
IO.puts Concat.join("Hello", "world") #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world
IO.puts Concat.join("Hello") #=> Hello
When using default values, one must be careful to avoid overlapping function definitions. Consider the following example:
defmodule Concat do
def join(a, b) do
IO.puts "***First join"
a <> b
end
def join(a, b, sep \\ " ") do
IO.puts "***Second join"
a <> sep <> b
end
end
If we save the code above in a file named "concat.ex" and compile it, Elixir will emit the following warning:
concat.ex:7: this clause cannot match because a previous clause at line 2 always matches
The compiler is telling us that invoking the join
function with two arguments will always choose the first definition of join
whereas the second one will only be invoked when three arguments are passed:
$ iex concat.exs
iex> Concat.join "Hello", "world"
***First join
"Helloworld"
iex> Concat.join "Hello", "world", "_"
***Second join
"Hello_world"
This finishes our short introduction to modules. In the next chapters, we will learn how to use named functions for recursion, explore Elixir lexical directives that can be used for importing functions from other modules and discuss module attributes.


Founded in 2006, CADCO was created to provide clients with high quality end-to-end commercial construction expertise. We are with you every step of the way, from pre-construction planning and design through building and on to post-construction.
Using the “design-build” model, CADCO is equipped to tackle every aspect of commercial construction and upfitting projects. This benefits clients by minimizing risk, shortening the delivery schedule, and streamlining the design, permitting, and construction processes..
Everyone involved in our projects is together under one roof, and this collaborative environment allows us to be a singular point of contact for our clients. Our focused, personalized attention enables us to provide customers a simplified, low-stress experience from start to finish. With over a decade of commercial construction experience and expertise, we pride ourselves in providing both outstanding customer service and quality craftsmanship. We are here to make your vision into reality.
With CADCO, your project not only comes in on time, but under budget as well, and the entire construction process is simplified. We oversee everyone involved in completing your project, which means there will be no surprises stemming from a lack of communication between independent, unconnected design and construction groups.


db-VERSION / \ java libdb_java | | src ... | com | sleepycat / \ db examples | | ... ...
This naming conforms to the emerging standard for naming java packages. When the java code is built, it is placed into a classes subdirectory that is parallel to the src subdirectory.
Makefile.win32 Makefile.unix
The java directory can be built using your make command and the appropriate Makefile. If you've never built java code before, there are two things you will need to do before issuing the make command.
First, make sure the java compiler (usually javac) is in your path. If you installed the sun JDK distribution in /usr/java , then the java tools are in the directory /usr/java/bin.
Make sure your classpath is set correctly. Set your environment variable CLASSPATH to contain at least the standard class library (perhaps in /usr/java/lib/classes.zip) and add the Berkeley DB classes in as well. Using the UNIX csh, this might be:
setenv CLASSPATH "/usr/java/lib/classes.zip:/db-VERSION/java/classes"
On Windows/95, your autoexec.bat would need to have something like:
set CLASSPATH="c:/java/lib/classes.zip;c:/db-VERSION/java/classes"
Note the use of semicolons on Windows. On Windows/NT, you'll set this variable in the control panel.
Now you can run make to build the java directory, e.g.:
cd db-VERSION/java make -f Makefile.unix
See Building a Shared Library Version of Berkeley DB for more information.
You MUST build Berkeley DB as a shared library before you proceed beyond this step.
On UNIX:
NB: The libdb_java/Makefile.unix Makefile is written to expect that the system compiler is named "gcc" and is the GNU C compiler. In addition, it uses compiler-specific options when building. If you are using a different compiler than gcc, you'll need to modify Makefile.unix to work with it.
First, edit the line at the beginning of libdb_java/Makefile.unix:
JAVAINSDIR= /usr/java1.1/
Change JAVAINSDIR to be the top level directory of your java JDK tree. This is the level above the bin and include directories. Then issue a make command in the libdb_java directory:
% cd db-VERSION/libdb_java % make -f Makefile.unix
On Win/:
Issue the nmake command in the libdb_java directory:
C:\db_distribution\libdb_java> nmake /f Makefile.win32
On Windows, you will want to set your PATH variable to include:
db-VERSION/libdb_java;db-VERSION/build_win32/debug
On UNIX, you will want to set LD_LIBRARY_PATH to include:
db-VERSION/libdb_java;db-VERSION/build_unix
These are the locations of your shared libraries. If you get a:
java.lang.UnsatisfiedLinkErrorexception when you run, chances are you do not have the PATH set up correctly.
Or, of course, you may copy the built dynamic libraries (libdb and java_db) to a directory already in your path.
To ensure that everything is running correctly, you may want to try a simple test from the example programs in:
db-VERSION/java/src/com/sleepycat/examples
(which should have been built in the "BUILDING JAVA" section above):
% java com.sleepycat.examples.AccessExample
This example program will prompt for text input lines which are then stored with their reversed text in a simple Btree named "db.access" in your current directly. Try giving it two lines of text and then end-of-file. Before it exits, you should see the reversed text. If you run it again, lines will be there from your previous run. This is an excellent check to make sure the fundamental things are working right.
NOTE: when you run some of the other examples on Solaris, you may get an "rmutex" libc error message. This is a known bug in Solaris 2.5, and it is fixed by Sun patch 103187-25. See the Sleepycat Software Release FAQ web page (www.sleepycat.com) for further information on this problem.


Emotional inteligence refers to the ability people have to recognise feelings, be it their own or others', and know how to act in a manner that respects those feelings, intelligently and with empathy. It enables us to function as a society, to avoid conflict and promotes growth, both of the group and the individual. It is important in a group working environment, to work efficiently and allow each member of the team to progress.
IQ refers to our ability to understant and develop logical thinking. It differs from EQ in the fact that it only involves the individual's mental capabilities, not in relation with others and relationships but when faced with complex tasks. Both are necessary for success but it has been shown that in the high leadership roles, the importance of EQ outweighs the importance of IQ.
It is important to possess a good EQ, and to work to improve our EQ in order to function well as a team member. To use an example, let's talk about climate change. There are a lot of great minds out there with great ideas and solutions to avoid environmental collapse. However, each of these great ideas, on their own, cannot change the current downward path humanity is on. If we imagine each country is just one person, we realise that each person is stuck in their desires for personal growth. We would need each of those people (countries) to improve their EQ in order to work together and resolve the problem. IQ alone cannot do it.


{% extends '_layouts/cp' %}
{% import '_includes/forms' as forms %}
{% set crumbs = [
{ label: 'Sift Workflow', url: url('settings/plugins/sift-workflow') }
] %}
{% set title = category.title %}
{% set groups = [] %}
{% for group in craft.app.userGroups.getAllGroups() %}
{% set groups = groups | merge([{ label: group.name, value: group.uid }]) %}
{% endfor %}
{% block actionButton %}
Delete
{% endblock %}
{% block content %}
{{ redirectInput('settings/plugins/sift-workflow') }}
{% set cols = [
{
type: 'select',
heading: 'User Group' | t('workflow'),
options: groups,
},
] %}
{{ forms.editableTableField({
label: 'Reviewer User Groups' | t('workflow'),
instructions: 'Select the user groups that your reviewers belong to. Reviewers are users that can review and edit submissions and pass them along for approval, but not publish live. The review process flows from the first to the last user group in the table.' | t('workflow'),
name: 'categoryReviewUserGroups',
id: 'categoryReviewUserGroups',
cols: cols,
rows: categoryReviewUserGroups,
addRowLabel: 'Add a user group' | t('workflow'),
first: true,
})|spaceless }}
{% endblock %}
{% css %}
table.editable tbody tr td {
text-align: left;
}
table.editable tbody tr td:first-of-type:before {
font-family: 'Craft';
content: 'rarr';
color: #9aa5b1;
vertical-align: middle;
margin-right: 5px;
}
{% endcss %}


The following options allow you to fine-tune your ODBC transfers. They are generally for advanced users.
Use NULL instead of empty strings
A null string is a string for which a value has never been entered while an empty string has zero length. Most databases support both NULL and empty strings (Oracle is the exception which converts empty strings to NULL strings). If you check this box, Stat/Transfer will write NULLS instead of empty strings into your database.
Prefer datetime over smalldatetime for MS SQL Server
The 'smalldatetime' type in MS SQL Server represents the dates between Jan 1,1900 to June 6, 2079 with accuracy to a minute. If this is sufficient for your needs and you want to save space, uncheck this option. The 'DateTime' type, in contrast, represents time values to an accuracy of close to 3 milliseconds and dates back to 1753.
Rows to read when scanning datetime variables
In some databases (including Access) there is only one date type, which can hold dates, times, and date/time values. Stat/Transfer will, by default, read ten rows of data to determine the type of such variables. If ten rows are not enough for your data, you can set a higher number here.
Prefer (w)varchar over (w)char
On output, if your data are stored in 'char' or its Unicode variant 'wchar', the length of the field will be equal to the length of its widest member. On the other hand, 'varchar' is stored in variable length fields that save storage when the length of the string data varies between cases. In general, you will want to leave this option at its default and write variable length string types when these are permitted.
Show the name of the table/view owner
A table or view in a database is identified by its owner and its name. If you are in an environment in which tables with different owners have the same name, you will need to check this option to make sure that you can select the proper table.
Append to Access and ODBC tables
This option (which is off by default), allows you to append your data to an existing database table.
Stat/Transfer will match as many variables as is possible to those already in the table and add your data to the matching columns. Obviously at least one column must match exactly and, in addition, the table must be free of constraints that would prohibit a simple 'append' operation, such as those requiring unique keys.


Procurement plans
A display of aggregated demand for goods and services per institution. This indicates what procurement of goods/services departments and entities plan to procure each quarter.
Deviations from procurement process
Requests from national departments, public entities, Constitutional institutions and provincial treasuries to deviate from standard bidding processes when procuring goods or services.
Expansions and extensions of contracts
Requests from national departments and public entities to expand and extend existing contracts rather than request new bids from potential suppliers to perform the work.


Preparation time
less than 30 mins
Cooking time
10 to 30 mins
Serves
Makes 1 20cm/8in cake
Dietary
A moist, spiced teatime cake filled with apple-flavoured cream cheese and topped with crunchy caramelized oats.
Pre-heat the oven to 190C/375F/Gas 5. Line 2 x 20cm/8in diameter cake tins with baking parchment.
Over a medium heat in a frying pan, toast the caraway seeds for 2-3 minutes until fragrant.
Sift the flours into the bowl of a food processor then add the sugar, baking powder and salt. Add the butter and eggs and process them until they form a batter. (You can also do this in a large bowl with a handheld electric mixer.)
Tip the batter into a large bowl and gently fold through the grated courgettes and the caraway seeds.
Divide the mixture equally between the two lined cake tins and cook for 25-30 minutes or until golden-brown and springy to the touch. Remove from the tins and cool on a rack.
For the filling, grate the apples into a pan and add the apple juice as required to keep apples moist. Add the sugar and bring the mixture to a simmer, stirring occasionally until the apples are softened, caramelized and all obvious wateriness has gone. Turn off the heat and leave to cool.
Add the butter and the cooled apple mixture to the bowl of a large food processor and blend to a purée. Stir this into the softened cream cheese and set aside.
For the topping, toast the oats in a dry frying pan until golden-brown and aromatic, then add the sugar to caramelize the oats.
Once the cakes are cool, spread a thick layer of the filling on onto one cake. Gently place the other cake onto the top, then spread a thinner layer of icing on top. Sprinkle with the toasted oats and serve.


Did you know you can use asciibots.js to generate unique avatars?
It's kind of like identicons. Just take a hash of the username and use 5 characters of the hash for each poster's unique robo id.
Replytron
I don't get it.
Roboposter 2048
For example, this page generates all the avatars from the usernames like this:
/* take an md5 hash of the username (here using CryptoJS) */
var hash = CryptoJS.MD5(username).toString(CryptoJS.enc.Hex);
/* take 5 characters from the hash as our id*/
var botId = hash.slice(-5);
/* call .asciibot() with our id. */
$(".bot", this).asciibot(botId);
It's kind of like identicons. Just take a hash of the username and use 5 characters of the hash for each poster's unique robo id.


HTML is the code that is used to structure a web page and its content. For example, content could be structured within a set of paragraphs, a list of bulleted points, or using images and data tables. As the title suggests, this course will give you a basic understanding of HTML and its components.
Anatomy of an HTML Document
What is an HTML element
HTML attributes
Nesting elements
Empty elements
HTML Comments
<!DOCTYPE html>   head elements - title, meta data, links   body content elements - text, images etc
That wraps up the basics of individual HTML elements.
<!DOCTYPE html> - the doctype. It is required preamble. They don't do much, and are basically just needed to make sure your document behaves correctly.
 - the html element. This element wraps all the content on the entire page and is sometimes known as the root element.
 - the head element. This element acts as a container for all the stuff you want to include on the HTML page that isn't the content you are showing to your page's viewers. This includes things like keywords and a page description that you want to appear in search results, CSS to style our content, character set declarations and more.
 - the body element. This contains all the content that you want to show to web users when they visit your page, whether that's text, images, videos, games, playable audio tracks or whatever else.

My cat is grumpy

An HTML element is defined by a start tag, some content, and an end tag. The main parts of our element are as follows:
opening tag -
 This states where the element begins. Also called start tag. This consists of the name of the element (in this case, p), wrapped in opening and closing angle brackets.
closing tag -
 This states the element ends. Also called end tag. This is the same as the opening tag, except that it includes a forward slash before the element name. Never skip the end tag
the content - This is the content of the element, which in this case, is just text.
the element - The opening tag, the closing tag and the content together comprise the element.
Visit here
HTML attributes provide additional information about HTML elements. Always specified in start tag and usually come in name/value pairs like: name="value"
href attribute - specifies the URL of the page the link goes to.

My cat is very

We can put elements inside other elements too — this is called nesting.
Make sure that your elements are properly nested

HTML elements with no content are called empty elements.

With comments you can place notifications and reminders in your HTML code. Comments are not displayed by the browser, but they can help document your HTML source code.


Home
Canvas
Graffiti Map
Community
Home
Services
Team
Contact
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx
xxxxxx


June 2, 12.45-13.30, room Data
June 9, 12.45-13.30, room Data
June 16, 12.45-13.30, room Data
3 dagen


Hi, my name is Debbie and I want to be a software developer. I have played around with coding for many years now, but really want to do it for a living. I love to solve problems and find web development to be fun and exciting. I love learning the logic of OOP and bending the code to my will. Javascript is fun, exciting and so dynamically fun! I enjoy Java as well. I love front end work but am very interested in the back end as well. I enjoy setting up a stack on my laptop and then just building things
Here is a fun game I made in one of my javascript classes, enjoy!
Matching GameTechnical Summary
I have done front end programming using html, css, and javascript. I have had lots of fun with bootstrap getting things up and running fast. I have used PHP and SQL on the back end. I have taken classes devoted to C as well as some devoted to learning programming concepts that used Java.
I have used frameworks/libraries/toolkits such as AngularJS, NodeJS, JQuery, Bootstrap, Bower, Drupal 7, and a little wordpress
As far as operating systems I have stuck mostly to Windows, and some linux while running a virtual machine
I have used git for version control as well as slack and trello for collaboration tools
Technical/Education Summary
I am currently enrolled in Launch Code and Washington University's Summer of Code. It is a 20 week long class consisting of three units. The first unit was learning Java and basic OOP programming. The second unit is called web development fundamentals. We are learning about the basics of web development and creating web apps. In the third unit we will create our own web app based on all that we have learned as a final project
I have completed the first three courses in Coursera's Full Stack Web Development Specialization. Each class built on the last culminating in building a single page application using AngularJS in the third class, "Front-End JavaScript Frameworks: AngularJS" Website


{% extends 'base_template.html' %} {% block title %}Yeargroup: {{ object.name }}{% endblock %} {% block body %}
Are you sure you want to delete "{{ object.name }}"?


Toying around with triangular numbers with certain digits, I did a search to see if others had found some neat formulas, and came across William James Tychonievich's blog entry that mentioned a pattern in the digits - every 10*2 (for decimal) triangular number ends in the same digit, and this series of 20 ending digits is a palindrome, i.e. ten digits then those same digits in reverse. According to the blog, this held for every base (2*2 for binary, 3*2 for trinary and so on), and also held for higher digits, just one power of the base higher.
The author did not feel he had the mathematics skill to express this algebraically or explore further, so I set to and tried myself. First thing I did was to look up the formula for triangular numbers: Trying out a few large numbers, incrementing n by, say 200 or 2000, and checking if the corresponding digit remained the same, showed that the pattern appeared to hold. I then tried to figure out the form of the number such an increment corresponds to; using k to mean the increment in the index of triangular numbers, I can use n and n + k in the above formula, and calculate the difference: and there seems to be the first answer; but cleaning it up makes it clearer, so let's swap variables and say yielding that is, if I make a step (of size k) over a number of triangular numbers equal to twice of a base (the b here), then the new triangular number is a multiple of b larger, which would preserve the last digit of the number in that base; similar if I said with p being the power, i.e. a number position in the base b, the result would be preserving the last p digits, and so on.
But what about the palindrome property? Can I prove this in a similar simple way? Since I need to mirror around a point that moves, I need to extract the period part, and to mirror I can subtract the remainder. I'll try working it out with two triangular numbers n and m using formulas here, b is still the base, p is the power, c is a constant selecting which period, and r is where in the period I'm looking - for n an offset forward from the first number in the period, for m working backwards from the next period (minus one to get the last number in this period). The difference between the two then becomes: and once again, the base to the power of the position turns out to be a factor of the difference, preserving the digits from that position out.


Access to this service is forbidden
An approver at your organisation can give you access.
After your permission is confirmed, close this window and try again. If the problem continues, you can contact the helpdesk.
An approver at your organisation can give you access.
After your permission is confirmed, close this window and try again. If the problem continues, you can contact the helpdesk.


“It wasn’t just our family involved anymore, I talked to experts about how to strengthen steel and manufacturers about molds and how to cast the parts. Based on feedback we modified the blade and made the surround just one piece of metal so it couldn’t break. I talked to lawyers about how to protect the idea and planned how to package and market my Kindling Cracker.”


Third World Problems
A community for good through Open Source
Website currently down for maintenance.
Follow the project on Twitter
File an issue on Github


This is a .NET client library for memcached written in C#. There is also a client for Membase's persistent memcached server.
Features:
You'll need .NET Framework 3.5 or later to use the precompiled binaries. To build client, you'll need Visual Studio 2010.
If you found any issues with the client, please submit a bug report at the Issue Tracker. Please include the following:
If you'd like to add a feature request please add some details how it is supposed to work.
The best bug reports come with a patch: fork the code on GitHub, then send a pull request so the fixes can be included in the next version.
First, have a look at the wiki. If you still have questions, please feel free to ask them on the mailing list, which can be found at: http://groups.google.com/group/enyim-memcached/


Why Leyline Phantom is awsome!
WHY LEYLINE PHANTOM IS AWSOME!
I will tell you
Malcom loves this card very much because it is so amazing.
As you can see Leyline Phantom is absaloutly amazing but you may be asking, "How do I get a Leyline Phantom? "
Well you see its very simple. All you have to do is go buy Magic the gathering cards from the set Gatecrash.
THE RULINGS OF LEYLINE PHANTOM
BACK TO THE BANANAS!


ruv: Detect and Remove Unwanted Variation using Negative Controls
Implements the 'RUV' (Remove Unwanted Variation) algorithms. These algorithms attempt to adjust for systematic errors of unknown origin in high-dimensional data. The algorithms were originally developed for use with genomic data, especially microarray data, but may be useful with other types of high-dimensional data as well. These algorithms were proposed by Gagnon-Bartsch and Speed (2012), and by Gagnon-Bartsch, Jacob and Speed (2013). The algorithms require the user to specify a set of negative control variables, as described in the references. The algorithms included in this package are 'RUV-2', 'RUV-4', 'RUV-inv', 'RUV-rinv', 'RUV-I', and RUV-III', along with various supporting algorithms.
Downloads:
Reverse dependencies:
Linking:
Please use the canonical form
https://CRAN.R-project.org/package=ruv
to link to this page.


| DOSE: |
50 mg |
oral |
2C-C |
(powder / crystals) |
This report is without any notes so bear with me. I consider myself a very experienced psychedelic explorer. This chemical caught me off guard, heres what happened.
Time of ingestion- 4:30 pm.
First effects noted +20 min
Empty stomach, however 20 minutes after ingestion I ate 1 quesadilla. By that time I was suprisingly feeling it already. The room and my computer seemed to slightly swirl in a very entertaining way and my vision had the microfine pixelation common to all 2c series chemicals I have tried before.
+40 min I leave my house to go out and explore my sourroundings (I do not reccommend this unless you have EXTENSIVE experience in psychedelic chemicals and alot of water in a back pack) listening to some GOA Gil and astral projection on my cd player. What I found once I reached the wooded area of my walk into town, is that I was at a full +2.5. But only while standing still. While walking the effects retreated to 'soft looks'. This was at perhaps +50 min. That piqued my curiosity, everything looked 'fluffy' like the trees and bushes I saw were actually softer than I knew them to be. My mood was extremely elevated and there was a much more felt body euphoria than with 2c-B and 2c-t-2.
At about +1hr 30min I had plateaued and was feeling very good. There were extreme feelings of closeness with the earth and I felt as if I wanted to never leave those woods. It was so peaceful and beautiful to see what nature had created in her glory. I am usually not a very spiritual or even emotional person, I like logic and science, exact sciences, but while feeling the effects I felt, I was a very docile and complacent spiritual emotionalist (I think I just made that word up) it felt good right down to my soul. After about 3 hrs after ingestion I began to come down and regretted it deeply. At about +4 I was down all the way with only an after effect of what had been so beautifully glorious. However, the feeling I felt then will stay with me forever.
Conclusion: this chemical is an exceptional one at that. It produced a heaviness on the chest which for me seemed to enhance feelings of spiritualness, emotions and well being. This would be an exceptional theraputic tool for the psycologist/psychiatrist when dealing with depressed patients. I believe this one is special (although, which one is not?) Every 2c series chemical has its therapeutic use, they just differ in which area of psychological therapy. One last reminder, do not take RESEARCH CHEMICALS WITHOUT THE USE OF A SCALE no one can eyeball 10-20-or even 30 mg without being off by at least 3-10 mg. So have fun and be safe peoples Peace on the Realist note, lsdteknology
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.


My Work
BlocJams
Spotify Inspired Music Application
Blocipedia
Wiki Knowledge Sharing
MontGem
JSON Parsing an API
ToDo With React & Redux
Functional To-do list, wired with Firebase


Name
Age
Sex
Delete
{{ people.name}}
{{ people.age}}
{{ people.sex}}
删除
Create New Person
Name:
age:
Sex:
Male
Female
create


Create a list with all possible keywords that fit to your product, service or business field. The more the better.
Forgot password? Restore
Login with


Hillsborough County Schools hiring more than 120 bus drivers
by WFTS Digital StaffTAMPA, Fla. — The Hillsborough County Public Schools is looking to hire bus drivers to get students in and out of school on time.
HILLSBOROUGH NEWS | The latest headlines from Hillsborough County
The school district is looking to hire 124 drivers for its job fair that is being held Tuesday night at Leto High School in Tampa. The school district said in a press release it needs 50 drivers to immediately fill open bus routes.
Hillsborough County Schools is hoping Tuesday's job fair will alleviate its bus driver shortage.
"It is one of the most important jobs in our district – transporting thousands of children to school safely every morning and back home every afternoon," Hillsborough County Schools said in a press release.
The school district is also hiring bus mechanics, food service workers, custodial operations and after-school childcare workers.
The job fair will be held at Leto High School from 5:30 p.m. to 7:30 p.m.


THE POSTMAN (1997)
A Film Review by James Berardinelli
RATING: ** OUT OF ****
United States, 1997 U.S. Release Date: 12/25/97 (wide) Running Length: 2:57 MPAA Classification: PG-13 (Violence, sex, brief nudity, profanity) Theatrical Aspect Ratio: 2.35:1
Cast: Kevin Costner, Will Patton, Larenz Tate, Olivia Williams, James Russo, Tom Petty Director: Kevin Costner Producers: Jim Wilson, Steve Tisch, and Kevin Costner Screenplay: Eric Roth and Brian Helgeland, based on the book by David Brin Cinematography: Stephen Windon Music: James Newton Howard U.S. Distributor: Warner Brothers
There are two ways that you can look at Kevin Costner's THE POSTMAN (not to be confused with the former Oscar contender of the same name, starring Massimo Troisi). The first is that it's a muddled but occasionally-brilliant lampoon of epic motion pictures. The other is that it's a horribly written, badly acted miscalculation of ISHTAR-like proportions. If you take THE POSTMAN at face value – that it's a straightforward, post-apocalyptic adventure tale, then it could seem like one of the worst movies of the year, if not of all time. However, since I laughed so hard during some scenes, I prefer to be a little kinder. Yes, it's a bad movie, but it's not one of the most unbearable theatrical experiences of the year. In fact, if you approach THE POSTMAN in the right mood, it's a highly watchable motion picture.
Admittedly, that's damning with faint praise, but I don't think THE POSTMAN is so gut-wrenchingly awful that it deserves *1/2 or less. With all of its rampant jingoism, cliched melodrama, and shameless attempts at emotional manipulation, THE POSTMAN could easily be viewed as a clever satire of epic adventures. In fact, there are times when it goes so far overboard that I found it virtually impossible to believe that director Kevin Costner wasn't winking at us. Sadly, based in part on the film's overall tone and in part on some of the director's comments, this doesn't seem to be the case. Except in certain moments that are obviously intended to be humorous, THE POSTMAN is not supposed to be a joke. But intent isn't everything, as fans of campy classics will point out. Regardless of what Costner wanted from the movie, it's still possible to enjoy it on a completely different level.
Of course, the running length is the real drawback. It's difficult to thrill to the dissonant rhythms of an "entertainingly bad" movie that threatens to drag for three hours. At half that length, THE POSTMAN might have been worth a recommendation, but, past the two hour mark, all of the cheese and corn starts becoming painful. Plus, a rather unfortunate attempt to add a message about consequences brings the movie to a grinding halt. We want to see overblown acts of heroism to go along with James Newton Howard's grandiose score and Stephen Windon's sweeping camerawork. Instead, we get a little too much of Kevin Costner brooding.
This side of a TV commercial, never has the U.S. Mail Service been so lauded (I wonder if they paid a heavy product placement fee). On top of that, there's such a cloying dose of patriotism that it's a wonder that Warner Brothers has been able to sell the film overseas (of course, the foreign markets may view all of the half-baked, pro-American slogans as one big joke). From a marketing standpoint, the only thing THE POSTMAN has going for it is the star, and his already-dipping stock is likely to take a precipitous tumble after this movie hits screens across the world.
The film opens in 2013 on the Great Salt Flats of Utah. In the aftermath of a cataclysmic world war, the human race has been fragmented and scattered. The government of the United States has collapsed, and now anarchy reigns. Small communities across the remains of the country jealously protect what they have by offering tribute to the dictatorial General Bethlehem (Will Patton), whose army of bandits and murderers controls everything. Any settlement that defies Bethlehem is quickly razed.
One day, a solitary wanderer (Costner) enters a small town to present a one-man Shakespeare show as a means of earning a little food and shelter. General Bethlehem pays a surprise visit to this village and the nameless loner is conscripted into the Holnist army. He is a rebellious man, however, and it isn't long before he escapes. Fleeing from search parties, he hides out in an old, broken down mail carrier's truck. Taking the full letterbag and the coat off a skeleton, he becomes the Postman. And, as he travels from town-to-town, speaking words of hope about the "Reformed Congress of the United States" and giving out letters, his reputation spreads, and Bethlehem determines that he's a threat.
Costner has done everything possible to make this film a crowd- pleaser. There are snappy one-liners, a romantic subplot for those who crave a little sex, and several manipulative scenes that are designed to get audiences to applaud wildly. Unfortunately, we're too busy laughing at all of the bloated silliness to remember to clap. Take, for example, one of the film's most emotional moments: a slow-motion shot of the Postman on horseback snatching a letter out of the hand of an eager boy. The brief sequence is filmed with such solemnity that it's all-but- impossible not to be amused, however briefly.
Costner plays the Postman like a combination of John Dunbar from DANCES WITH WOLVES and the mariner from WATERWORLD. It's not a particularly energetic or interesting performance, and it's made even more tiresome by the hero's reluctance to act decisively (this wastes a good forty-five minutes). As the villain, Will Patton is generic. He's neither good nor bad, and doesn't bring much more to the part than we'd get from a Dennis Hopper or a Gary Busey. Larenz Tate's character, Ford Lincoln Mercury, is the stereotypical idealistic enthusiast, and Tate puts about as much energy into the role as it deserves. The only legitimate spark is generated by newcomer Olivia Williams, who plays Abby, the Postman's love interest. She's quite good, and manages to develop an independent female character who's not always in need of rescuing, but her above-average effort is wasted in this material.
It's hard to believe that the same man who directed a modern classic, DANCES WITH WOLVES, could be responsible for something this horribly mishandled.  Probably at the very beginning. THE POSTMAN is a bad idea, poorly executed.  (One classic line: Abby, addressing the Postman, says in a heartfelt voice, "You give out hope like it was candy in your pocket." Puhleeze! Give me a break!) When all is said and done, however, at least it can amuse us. And, even at an interminable three hours, it still offers more solid laughs than half of this year's so-called "comedies."
Copyright 1997 James Berardinelli
- James Berardinelli e-mail<EMAIL_ADDRESS>Now with more than 1300 reviews... The ReelViews web site: http://movie-reviews.colossus.net/
"No art passes our conscience in the way film does, and goes directly to our feelings, deep down into the dark rooms of our souls"
- Ingmar Bergman
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


Every true "foodie" worth their salt knows that some of the best food in any city can be found on food trucks - but knowing when and where those trucks will be can be next to impossible, and discovering new ones often relies on word-of-mouth that is long on tales of delicious, but short on actual details. FoodTruck TrackR was designed to make finding and eating at a food truck fast, easy and fun. Quickly see all of our Operator partners' nearby food trucks that currently open, view their current real-time GPS location, know the scheduled arrival and departure times, view photos, read customer reviews and much more, all in our easy to use app. Try FoodTruck TrackR today, and enjoy the best food YOUR city has to offer.
Alexis Villaraza
Project lead
Jorge Manzur
Frontend developer
Sami Al Aloosi
Backend developer
Tom Bauer
Backend developer
Prince Buduru
User interface
Bryan Adams
User interface


When it comes to careers in software development, it is a must for aspiring developers to work on their own projects. Developing real-world projects is the best way to hone your skills and materialize your theoretical knowledge into practical experience. Here is the list of projects to guide you.
In an online auction, buyers and sellers engage in transactional business, wherein buyers purchase items through price bidding. Here, the bids have a starting price and an ending time.
One of the best ideas to start experimenting you hands-on computer science projects for students is face detection software. This project focuses on building a face detection software using the OpenCV library.
This project involves the creation of an evaluation system that can analyze the academic performance of students by utilizing the fuzzy logic method. In the fuzzy logic method, you will consider three parameters
This project focuses on building an e-Authentication system using a combination of QR code and OTP for enhanced security. The e-Authentication system is designed to avoid hacking of accounts through shoulder .
This is a project where you will design a cursor that can move through desktop and perform actions based on hand gestures. The system’s object movement will be based on RGB (red, green, and blue) colour – it can detect RGB
This is one of the interesting computer science project ideas to create. As the name suggests, this Computer Science project involves building a prediction system that can analyze and predict the crime rate of a particular location


Reluctantly Remote, and loving it
I have to admit, most of my career I’ve treated remote collaboration as a necessary evil.
I’m a big fan of collocation. I love sticky notes, magic charts and colourful tape. I love walls so much whenever I see pictures hanging on them I’m like, why are they wasting good wall space for those useless pictures? I love pair and mob programming. I love highly engaged, participant centred workshops. I love retrospectives, and I do elaborate ones featuring lots of pair and group conversation, arts and crafts, and role playing.
For years I’ve lived this way, preaching customer and partner interaction, NIHITO, user observation, face to face collaboration and working together shoulder to shoulder.
Then, the first shoe dropped, I joined an early stage startup building the knowledge collaboration database of the future, TerminusDB.
Suddenly, I had a distributed team, half of the engineers are in Utrecht, half of the engineers, along with the business team are in Dublin, a developer relations person in London, and me in Berlin.
So, I started making everyone fly around, we had workshops and collocated work in the Netherlands, and in Ireland, we started to develop our flow of design and delivery practises.
The idea was that we would do design and planning in person, on walls with stickies and stuff, then convert these to digital representations and do delivery work back home, but try to divide systems such that related work could be done by work enters which are mostly collocated. So, core database development in Utrecht and web platform work in Dublin.
This meant our CTO would basically commute from Dublin to Utrecht, and our DevRel person would basically commute from London to Dublin, and I would also be travelling continuously. But hey, that’s been more or less what I’ve been used to for basically forever, and this is the framework that I’ve been recommending to teams for a long time.
We chose Trello as our online kanban, and where already using Slack and Github, plus Google Apps and Zoom. So, we were somewhat remote already, but not really.
Realizing that it would be cool if we could find ways to do some of the design and planning work online, as there would never be enough time to do all of it in person, I started investigating online collaboration tools, and having conversations with colleagues about best tools and practises.
Then, the other shoe dropped. A worldwide pandemic. Everyone is working from home. Travel is not an option, and our customers can not be visited.
Now what?
Day one we left our physical offices in Dublin and Utrecht, and moved into our new virtual office: Discord.
Discord is a platform for gamers to play online games together, it provides text chat channels, like Slack, but also voice channels which are like meeting rooms that people can have voice meetings in.
The ability to have different channels for teams as well as for company meetings, and the ability to quickly see that people are in a given voice channel, provides for a much more ad-hoc experience, you can see when and where people are meeting, drop in and say hi, or notice meetings are happening when maybe you didn’t notice in your calendar.
This feels much more like an office experience than scheduled video conferences, and allows for more casual interactions with less friction in jumping on voice chats. It’s not quite collocation, but it’s not a bad facsimile.
Discord also allows a user to go live and share their screen, this was designed for streaming the game you are playing so that others can watch you play. It also works well for pair and mob programming and presentations.
If anything, moving to Discord has actually increased the time we spend paring and mobbing. Something we’re very happy about, not to mention the reduced air miles.
We are writing more code with greater quality, spending less money, emitting less carbon, and abiding by needed social distancing practises during the pandemic. Other than perhaps worsening the teams personal hygiene and fashionability, this has been a real improvement, and a practise we will continue even when the pandemic is behind us.
So far so good, however, pairing and mobbing and presentations are great for the delivery portion of our workflow, but there is still the question of design and planning. While I had begun my investigations in earnest, now we’re all in. It’s go remote or go home! No wait. It’s stay home or no go!  Something like that.
The question is how do I facilitate agile design and planning practises when I can’t see everyone, when I can’t get them to write sticky notes, and I don’t have a wall to stick them on.
So far, I’ve not really been a big fan of any of the online tools I’ve tried. They are either too fiddly, requiring the mouse ninja skills of a master Photoshop jockey, or too limited, implementing a very rigid version of popular practises and not allowing you to paint outside the lines or vary the practice when the situation calls for it. They make it hard or impossible to combine practises or invent new ones, as I am wont to do.
Good luck facilitating an online session when you need to start with an hour long introduction to the tools, and let’s put aside the issues of ill-fitting pricing models for now.
In the end, after trying every tool available online and putting myself at risk of repetitive strain injury just from the amount of “Hi, I’m Bill from Customer Success” emails I will need to unsubscribe from , some hope is emerging.
With Discord as our virtual office, and with everybody getting used to voice channels as opposed to video conferences, this leaves our eyes free to focus on real time collaboration tools instead of video. While screen sharing and video are very useful tools, for working sessions like planning and design workshops they are better avoided.
Instead of video or screen sharing, real time collaboration tools allow everyone to work together at the same time within the collaboration app, so nobody is sharing their screen, everyone is using the same software at the same time and seeing the same state.
The first tool we added was Lucid Meetings. Lucid is not a conferencing tool, we use Discord voice channels to talk during meetings.
Lucid is a real time meeting tool that allows you to create an agenda, and step through it together with everyone at the same time. During the meeting, everyone sees the current agenda item being discussed.
This is super important if you will also be use other tools during the meeting, as you can provide links and instructions in the agenda. One of the biggest challenges is keeping a group of remote people in sync. A real time agenda tool like Lucid is really helpful for this.
Lucid also has a chat interface, allows everyone to write notes, add action items and other records, which are not only emailed to everyone after the meeting, but also kept in lucid and available for review at future meetings.
There is also a speaker queue, document attachments and other features required for facilitating meetings and recording outcomes. Lucid is built by meeting experts, includes templates and facilitator guides for common meeting types, and has a friendly and very helpful community.
So, now that I can plan the session and keep everyone on the same page, the next, and trickiest bit is visual collaboration, how do I replace creating simple canvases with tape and sticky notes? Although honourable mention goes to MetroRetro and Miro, both very cool tools, our team chose Mural. Not sure why all these tools start with an M. Maybe it’s like a secret coded message of some kind.
Mural is a real time visual collaboration tool that allows people to draw on a canvas at the same time, add sticky notes, shapes and pictures. What sets it apart are it’s “Facilitator Superpowers.”
Facilitators can build outlines, that define parts of a canvas or steps in a Practise, and then “summon” participants so that they are all looking at the same part of the canvas at the same time, and hide and reveal portions of the canvas as required to advance the practise. It also has plenty of popular templates and frameworks for popular practises, but makes it easy to combine them and make your own templates. It also has a timer, and a voting feature.
I’ve successfully created templates for my own practises with it and used them to run remote meetings.
So, while our journey into remote design and planning practises is just beginning, and many challenges remain, Discord, Lucid Meetings and Mural give us a pretty solid base to build on.
But, OK, I confess “loving it” was an exaggeration, I still miss working face to face, but we’re coping and even when the pandemic is over, I’m sure that remote work and the practises we are developing will remain a key part of our way of working.
Venture Communist.


It was the day when I was born on this beautiful earth. Probably I didn't know, but that was the most happiest moment of my life. Many people smiled with me. From then on, it's being the journey full of laughter (sometimes, without reason, my sister made fun of me often), got dirty in the mud, jumped roof tops to catch the kite and did all those strange things you could think of. And yes, I fought a lot with my beloved sister.
In between all these, I was also kinda nerd with the dream to do something big in my life. Those dream are still fresh... Currently, I am Software Developer in Booking.com, Amsterdam. I am very proud of what I do, I train computers perform tasks which humans find boring. This is changing the world, the way we work and we collaborate. Isn't it cool!
I graduated in Computer Science from one of the top tier university of India, Indian Institute of Information Technology in 2014.
It was my first job after graduating from Indian Institute of Information Technology, Allahabad in 2014. I worked here till March 2017
In 2017, I wanted to take a turn in life to explore different city and learn even more. I switched to Microsoft India Development Center, Bangalore. It was great learning experience working in top tier companies of the world.
Well, life was not about it. Exploring international culture, meeting with people of different countires and learning the E-Commerce business was yet another aspiration. I searched this nice opportunity and moved here in 2018
In my family, we are 5 members. My father is a self-made man and is my life gear. He is currently running whole sale business of rice.   She is currently settled in the USA. My brother in law is a gentleman who is always a friend and mentor to me.


The following properties can be set on any object when creating it. This also lists their default values if they are not set.
lineWidth 5
strokeStyle "#000000"
fillStyle "#000000"
lineCap "round"
lineJoin "miter"
lineDash []
miterLimit 10
shadowColor null
shadowOffsetX 0
shadowOffsetY 0
shadowBlur 0
globalAlpha 1
translationX 0
translationY 0
shake 0
blendMode "source-over"
All of these defaults are defined on the glc.styles
property. So you can change any of these globally by writing, for example:
glc.styles.lineWidth = 20;
list.addCircle({
stroke: true,
fill: false,
radius: [50, 80]
});
Now, all objects will be drawn with a line width of 20 pixels, unless they explicitly set their own lineWidth
property.
Note that you can not set default animations on glc.styles
, only single values. Animations are only parsed within an object's property definition.
There is one additional property on glc.styles
that does not apply to individual objects:
backgroundColor "#ffffff"
This is a global style only. The backgroundColor
is only used to draw the main background of the animation and is not used by objects. It is not animatable. If you want to animate the background color, just create a rect behind all the other objects and animate its color.
You can create a background color by doing something like "rgba(0, 0, 0, 0.1)"
. This has the result of partially covering the previous frame with black. After multiple frames, the background becomes mostly black, but you will sometimes see "trails" of moving objects. This can be used to create some great effects. Note, that the non-standard 8-digit hex string like "#80000000"
cannot be used here because this value is not parsed by the GLC color parsing system.
All of the other styles do pretty much what they do in the HTML5 Canvas drawing API. The exceptions are:
lineDash
property, which is a setLineDash
method on the 2d rendering context.translationX
and translationY
, which are translate(x, y)
on the context."#80ff0000"
shake
property adds an adjustable jitter to any object it is applied to, randomly changing its position by a small amount on each frame.blendMode
property maps to the Canvas globalCompositeOperation
property. It's exactly the same. I just didn't feel the need to make you type "globalCompositeOperation" every time you need to use it.Although colors are already pretty powerful in GLC, I added a color module that makes defining colors even easier. You can access this as glc.color
and it is now aliased in the template to simply be color
.
The color module contains several methods that return color strings that can be used for fill styles, stroke styles, shadow colors or background colors. Here are all the methods:
- color.rgb(r, g, b)
- color.rgba(r, g, b, a)
- color.gray(shade)
- color.randomRGB()
- color.randomRGB(min, max)
- color.randomGray()
- color.randomGray(min, max)
- color.num(number)
- color.hsv(h, s, v)
- color.hsva(h, s, v, a)
- color.animHSV(h, s, v)
- color.animHSVA(h, s, v, a)
- color.randomHSV(minH, maxH, minS, maxS, minV, maxV)
Some of these simply make it easier to define colors using numbers for the component channels.
fillStyle: color.rgb(255, 128, 0)
or...
fillStyle: color.rgba(255, 128, 0, 0.5)
The color.num
method lets you pass in a single integer that will be converted to a color string. This is usually done with a hexadecimal based number.
fillStyle: color.num(0xff8000)
Note that the num
method only supports 24-bit numbers, so no alpha channel. Which is to say that the color will always be fully opaque.
You can also easily define a grayscale color with the color.gray
method. Just pass it a value from 0 to 255.
fillStyle: color.gray(128)
Then there are methods for generating random colors or grays. color.randomRGB()
will return a random color with full alpha.
fillStyle: color.randomRGB()
You can also pass minimum and maximum parameters to this method. For example, the following will generate a random color where all of the components have a value between 0 and 128. This will be a darker color, whatever it winds up being.
fillStyle: color.randomRGB(0, 128)
Whereas this example will generate colors where all the components have higher values - between 128 and 255:
fillStyle: color.randomRGB(128, 255)
Then there's the color.randomGray()
method. This works the same way. With no parameters, you'll get a random gray from the full spectrum of grays.
fillStyle: color.randomGray()
Or you can pass in min and max values to set a range of grays where your random one will be pulled from.
fillStyle: color.randomGray(0, 128)
Finally, there are two methods for getting HSV (hue, saturation, value) based colors. First there is color.hsv(h, s, v)
. Here, you pass a value from 0 to 360 for hue. This determines the base color. Then a value from 0 to 1 for saturation and 0 to 1 for value. Saturation controls how much of the base hue will be in the final color, where 1 is a fully saturated value and 0 will give you white. And value controls how dark the color is, where 1 is as bright as it can be and 0 will be black.
fillStyle: color.hsv(30, 1, 1)
There's also a version with alpha:
fillStyle: color.hsva(30, 1, 1, 0.5)
And, of course, there's a random method for hsv: color.randomHue(min, max, s, v)
. With this one, the min
and max
parameters, as well as s
and v
, are all required. The following will generate colors with a orange to yellow hue:
fillStyle: color.randomHSV(30, 60, 1, 1, 1, 1)
A note on animating with the color module. All of the methods discussed so far return valid color strings, so they can all be animated just as if you'd assigned any other basic string. For example:
fillStyle: [color.rgb(255, 0, 0), color.gray(128)]
And you can mix and match them with any other color strings:
fillStyle: [color.randomRGB(), "blue"]
The only caveat is on using the color.hsv
method. The values you assign here will be converted to a color string - which is rgb based - BEFORE animating. So you may not get the result you're looking for when animating between two hsv-defined colors. Take the following example:
fillStyle: [color.hsv(0, 1, 1), color.hsv(360, 1, 1)]
You might expect that to animate through the full spectrum of colors, giving you a rainbow effect. That's not what you'll get though. Actually hsv(0, 1, 1)
will be converted to "#ff0000"
. And hsv(1, 1, 1)
will convert to the exact same thing. So you'll be animating from red to red - no visible animation at all.
That's what the color.animHSV
method is for. This takes six values - start and end parameters for each of h, s and v, and will animate between them as you would expect.
fillStyle: color.animHSV(startH, endH, startS, endS, startV, endV)
This will recalculate a new hsv value on each frame, so it is actually animating through various hues. If you try this one, I suggest you try it in single mode, no easing, with a duration of at least 5. Otherwise, the entire spectrum will be moving by so quickly, it will just look like random flashing colors. Animating hues often works better for smaller ranges, such as a min and max of 30 and 60, which will move between an orange and a yellow color.
And, for the sake of completeness, the alpha version:
fillStyle: color.animHSVA(startH, endH, startS, endS, startV, endV, startA, endA)
For a bit more in depth discussion of the color module, check out this post.
Gradients, even in native canvas, are complex. Creating a single gradient is complicated enough, so it was a challenge to allow for a method of animating gradients without making it any more complicated. One of the main design decisions, good or bad, in GLC was to match the native canvas drawing API as much as possible. In canvas, you create gradients by calling context.createLinearGradient()
or context.createRadialGradient()
and then adding colors at specific spots in the gradient by calling gradient.addColorStop()
. This is well documented elsewhere on the web, so I'm not going to go into that much here.
But basically, you'll be using the same API to make gradients in GLC. The big difference is that the gradients you create in GLC will be animatable, just like everything else.
The methods for creating gradients have been added to the color module (which again is at glc.color
, and aliased to simply color
in the template.js
file).
So, to create a linear gradient, you would say:
var gradient = color.createLinearGradient(x0, y0, x1, y1);
This creates a linear gradient that starts at point x0, y0
and goes to x1, y1
. Now we need to add color stops. Say we want the color to be red at point x0, y0
and gradiently change to blue when it reaches x1, y1
. We say:
var gradient = color.createLinearGradient(x0, y0, x1, y1);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
You can add as many stops as you want. Just ensure that you keep the positions in the range of 0 - 1.
var gradient = color.createLinearGradient(x0, y0, x1, y1);
gradient.addColorStop(0, "red");
gradient.addColorStop(0.5, "green");
gradient.addColorStop(1, "blue");
Now, the gradient will start at red, move through green at the midway point, and end at blue. We can then simply assign this to the fillStyle
or strokeStyle
property of any object we are drawing. So here's what we have:
function onGLC(glc) {
glc.loop();
glc.size(200, 200);
var list = glc.renderList,
width = glc.w,
height = glc.h,
color = glc.color;
var gradient = color.createLinearGradient(0, -100, 0, 100);
gradient.addColorStop(0, "red");
gradient.addColorStop(0.5, "green");
gradient.addColorStop(1, "blue");
list.addCircle({
x: 100,
y: 100,
radius: 100,
fillStyle: gradient
});
}
Here, the gradient goes from point 0, -100 to point 0, 100. This is relative to the center of the circle we are drawing. Since the circle has a radius of 100, the gradient will go from the top of the circle to the bottom. And here's what this gives us:
The center of the object distinction is unique to GLC. In native canvas, the gradient is always centered at the top left of the canvas itself. This makes calculating your gradient sizes and positions to match what you're drawing a bit tricky.
But for many of the objects in GLC the gradient is centered on the object, so things generally become a whole lot simpler.
The gradient is centered on the object for the following shapes: circle, gear, heart, oval, poly, rect, star and text. These objects all have a size and position that is known beforehand. Also, these are the objects most likely to be filled, and gradients are generally more commonly used on fills than on strokes. So this makes filling these objects with a gradient very easy.
When using gradients on other objects, such as curves, lines and paths, the gradient will most likely start at the default top left of the canvas and you'll have to work out where you want it from there, just like in native canvas. In some objects, such as the ray, the gradient will be centered on the first point of the ray. So you might need to experiment a bit to see where the gradient is actually starting and adjust it from there.
For radial gradients, the process is the same, but you'd call color.createRadialGradient(x0, y0, r0, x1, y1, r1)
. Again, you're specifying two points, but also two radii. Basically the gradient goes between two circles. Usually these are somewhat concentric circles, with one very small, and the other the size of your object. So we have this:
function onGLC(glc) {
glc.loop();
glc.size(200, 200);
var list = glc.renderList,
width = glc.w,
height = glc.h,
color = glc.color;
var gradient = color.createRadialGradient(0, 0, 0, 0, 0, 100);
gradient.addColorStop(0, "red");
gradient.addColorStop(0.5, "green");
gradient.addColorStop(1, "blue");
list.addCircle({
x: 100,
y: 100,
radius: 100,
fillStyle: gradient
});
}
The only difference here is that we created a radial gradient. The first point is 0, 0 with a radius of 0. The second point is also 0, 0, with a radius of 100. Color stops are the same. So we get:
Now, on to animating! A lot of work went into making this as easy as possible while still following the canvas API. In the end, all we have to do is create two gradients, and assign them as an array to fillStyle
. GCL will animate between them. It will animate the points and radii of the gradients, and the positions and colors of all the color stops!
Here you go:
function onGLC(glc) {
glc.loop();
glc.size(200, 200);
var list = glc.renderList,
width = glc.w,
height = glc.h,
color = glc.color;
var gradient1 = color.createRadialGradient(0, 0, 0, 0, 0, 100);
gradient1.addColorStop(0, "red");
gradient1.addColorStop(0.5, "green");
gradient1.addColorStop(1, "blue");
var gradient2 = color.createRadialGradient(0, 0, 0, 0, 0, 100);
gradient2.addColorStop(0, "green");
gradient2.addColorStop(0.5, "blue");
gradient2.addColorStop(1, "red");
list.addCircle({
x: 100,
y: 100,
radius: 100,
fillStyle: [gradient1, gradient2]
});
}
Here, all I did was change the colors, but you could change just about anything. The result:
Now before you ask, NO, it's not possible to animate between different kinds of gradients. For example, you can't animate between a solid fill and a gradient, or between a linear and radial gradient. You could, of course, create two gradients, and have the colors all the same in one. This would, in effect, create a solid fill or stroke. But since it's really a gradient, it would animate to a different gradient.
Also, the number of color stops in the two gradients should be equal. If they aren't, some color stops might be dropped, or your computer might blow up.


1 For this reason Egypt was intersected. This king also (they said) divided the country among all the Egyptians by giving each an equal parcel of land, and made this his source of revenue, assessing the payment of a yearly tax.
2 And any man who was robbed by the river of part of his land could come to Sesostris and declare what had happened; then the king would send men to look into it and calculate the part by which the land was diminished, so that thereafter it should pay in proportion to the tax originally imposed.
3 From this, in my opinion, the Greeks learned the art of measuring land; the sunclock and the sundial, and the twelve divisions of the day, came to Hellas from Babylonia and not from Egypt.