There are no unique textbooks which cover the material to be discussed. For each week however, we will, in addition to our own lecture notes, send links to additional literature. This can be articles or chapters from other textbooks. A useful textbook is however
This book has its main focus on spin-models, but many of the concepts are general. Chapters 1 and 2 contain a good discussion of the statistical foundation.
Most quantum mechanical problems of interest in for example atomic, molecular, nuclear and solid state physics consist of a large number of interacting electrons and ions or nucleons.
The total number of particles \( N \) is usually sufficiently large that an exact solution cannot be found.
Typically, the expectation value for a chosen hamiltonian for a system of \( N \) particles is
$$ \langle H \rangle = \frac{\int d\boldsymbol{R}_1d\boldsymbol{R}_2\dots d\boldsymbol{R}_N \Psi^{\ast}(\boldsymbol{R_1},\boldsymbol{R}_2,\dots,\boldsymbol{R}_N) H(\boldsymbol{R_1},\boldsymbol{R}_2,\dots,\boldsymbol{R}_N) \Psi(\boldsymbol{R_1},\boldsymbol{R}_2,\dots,\boldsymbol{R}_N)} {\int d\boldsymbol{R}_1d\boldsymbol{R}_2\dots d\boldsymbol{R}_N \Psi^{\ast}(\boldsymbol{R_1},\boldsymbol{R}_2,\dots,\boldsymbol{R}_N) \Psi(\boldsymbol{R_1},\boldsymbol{R}_2,\dots,\boldsymbol{R}_N)}, $$an in general intractable problem.
This integral is actually the starting point in a Variational Monte Carlo calculation. Gaussian quadrature: Forget it! Given 10 particles and 10 mesh points for each degree of freedom and an ideal 1 Tflops machine (all operations take the same time), how long will it take to compute the above integral? The lifetime of the universe is of the order of \( 10^{17} \) s.
As an example from the nuclear many-body problem, we have Schroedinger's equation as a differential equation
$$ \hat{H}\Psi(\boldsymbol{r}_1,..,\boldsymbol{r}_A,\alpha_1,..,\alpha_A)=E\Psi(\boldsymbol{r}_1,..,\boldsymbol{r}_A,\alpha_1,..,\alpha_A) $$where
$$ \boldsymbol{r}_1,..,\boldsymbol{r}_A, $$are the coordinates and
$$ \alpha_1,..,\alpha_A, $$are sets of relevant quantum numbers such as spin and isospin for a system of \( A \) nucleons (\( A=N+Z \), \( N \) being the number of neutrons and \( Z \) the number of protons).
There are
$$ 2^A\times \left(\begin{array}{c} A\\ Z\end{array}\right) $$coupled second-order differential equations in \( 3A \) dimensions.
For a nucleus like beryllium-10 this number is 215040. This is a truely challenging many-body problem.
Methods like partial differential equations can at most be used for 2-3 particles.
The physics of the system hints at which many-body methods to use.
We start with the variational principle. Given a hamiltonian \( H \) and a trial wave function \( \Psi_T \), the variational principle states that the expectation value of \( \langle H \rangle \), defined through
$$ E[H]= \langle H \rangle = \frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})H(\boldsymbol{R})\Psi_T(\boldsymbol{R})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})}, $$is an upper bound to the ground state energy \( E_0 \) of the hamiltonian \( H \), that is
$$ E_0 \le \langle H \rangle . $$In general, the integrals involved in the calculation of various expectation values are multi-dimensional ones. Traditional integration methods such as the Gauss-Legendre will not be adequate for say the computation of the energy of a many-body system.
The trial wave function can be expanded in the eigenstates of the hamiltonian since they form a complete set, viz.,
$$ \Psi_T(\boldsymbol{R})=\sum_i a_i\Psi_i(\boldsymbol{R}), $$and assuming the set of eigenfunctions to be normalized one obtains
$$ \frac{\sum_{nm}a^*_ma_n \int d\boldsymbol{R}\Psi^{\ast}_m(\boldsymbol{R})H(\boldsymbol{R})\Psi_n(\boldsymbol{R})} {\sum_{nm}a^*_ma_n \int d\boldsymbol{R}\Psi^{\ast}_m(\boldsymbol{R})\Psi_n(\boldsymbol{R})} =\frac{\sum_{n}a^2_n E_n} {\sum_{n}a^2_n} \ge E_0, $$where we used that \( H(\boldsymbol{R})\Psi_n(\boldsymbol{R})=E_n\Psi_n(\boldsymbol{R}) \). In general, the integrals involved in the calculation of various expectation values are multi-dimensional ones. The variational principle yields the lowest state of a given symmetry.
In most cases, a wave function has only small values in large parts of configuration space, and a straightforward procedure which uses homogenously distributed random points in configuration space will most likely lead to poor results. This may suggest that some kind of importance sampling combined with e.g., the Metropolis algorithm may be a more efficient way of obtaining the ground state energy. The hope is then that those regions of configurations space where the wave function assumes appreciable values are sampled more efficiently.
The tedious part in a VMC calculation is the search for the variational minimum. A good knowledge of the system is required in order to carry out reasonable VMC calculations. This is not always the case, and often VMC calculations serve rather as the starting point for so-called diffusion Monte Carlo calculations (DMC). DMC is a way of solving exactly the many-body Schroedinger equation by means of a stochastic procedure. A good guess on the binding energy and its wave function is however necessary. A carefully performed VMC calculation can aid in this context.
Choose a trial wave function \( \psi_T(\boldsymbol{R}) \).
$$ P(\boldsymbol{R})= \frac{\left|\psi_T(\boldsymbol{R})\right|^2}{\int \left|\psi_T(\boldsymbol{R})\right|^2d\boldsymbol{R}}. $$This is our new probability distribution function (PDF). The approximation to the expectation value of the Hamiltonian is now
$$ E[H(\boldsymbol{\alpha})] = \frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R},\boldsymbol{\alpha})H(\boldsymbol{R})\Psi_T(\boldsymbol{R},\boldsymbol{\alpha})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R},\boldsymbol{\alpha})\Psi_T(\boldsymbol{R},\boldsymbol{\alpha})}. $$
Define a new quantity
$$ E_L(\boldsymbol{R},\boldsymbol{\alpha})=\frac{1}{\psi_T(\boldsymbol{R},\boldsymbol{\alpha})}H\psi_T(\boldsymbol{R},\boldsymbol{\alpha}), \label{eq:locale1} $$called the local energy, which, together with our trial PDF yields
$$ E[H(\boldsymbol{\alpha})]=\int P(\boldsymbol{R})E_L(\boldsymbol{R}) d\boldsymbol{R}\approx \frac{1}{N}\sum_{i=1}^N E_L(\boldsymbol{R_i},\boldsymbol{\alpha}) \label{eq:vmc1} $$with \( N \) being the number of Monte Carlo samples.
The Algorithm for performing a variational Monte Carlo calculations runs thus as this
Observe that the jumping in space is governed by the variable step. This is Called brute-force sampling. Need importance sampling to get more relevant sampling, see lectures below.
The radial Schroedinger equation for the hydrogen atom can be written as
$$ -\frac{\hbar^2}{2m}\frac{\partial^2 u(r)}{\partial r^2}- \left(\frac{ke^2}{r}-\frac{\hbar^2l(l+1)}{2mr^2}\right)u(r)=Eu(r), $$or with dimensionless variables
$$ -\frac{1}{2}\frac{\partial^2 u(\rho)}{\partial \rho^2}- \frac{u(\rho)}{\rho}+\frac{l(l+1)}{2\rho^2}u(\rho)-\lambda u(\rho)=0, \label{eq:hydrodimless1} $$with the hamiltonian
$$ H=-\frac{1}{2}\frac{\partial^2 }{\partial \rho^2}- \frac{1}{\rho}+\frac{l(l+1)}{2\rho^2}. $$Use variational parameter \( \alpha \) in the trial wave function
$$ u_T^{\alpha}(\rho)=\alpha\rho e^{-\alpha\rho}. \label{eq:trialhydrogen} $$
Inserting this wave function into the expression for the local energy \( E_L \) gives
$$ E_L(\rho)=-\frac{1}{\rho}- \frac{\alpha}{2}\left(\alpha-\frac{2}{\rho}\right). $$A simple variational Monte Carlo calculation results in
| \( \alpha \) | \( \langle H \rangle \) | \( \sigma^2 \) | \( \sigma/\sqrt{N} \) |
| 7.00000E-01 | -4.57759E-01 | 4.51201E-02 | 6.71715E-04 |
| 8.00000E-01 | -4.81461E-01 | 3.05736E-02 | 5.52934E-04 |
| 9.00000E-01 | -4.95899E-01 | 8.20497E-03 | 2.86443E-04 |
| 1.00000E-00 | -5.00000E-01 | 0.00000E+00 | 0.00000E+00 |
| 1.10000E+00 | -4.93738E-01 | 1.16989E-02 | 3.42036E-04 |
| 1.20000E+00 | -4.75563E-01 | 8.85899E-02 | 9.41222E-04 |
| 1.30000E+00 | -4.54341E-01 | 1.45171E-01 | 1.20487E-03 |
We note that at \( \alpha=1 \) we obtain the exact result, and the variance is zero, as it should. The reason is that we then have the exact wave function, and the action of the hamiltionan on the wave function
$$ H\psi = \mathrm{constant}\times \psi, $$yields just a constant. The integral which defines various expectation values involving moments of the hamiltonian becomes then
$$ \langle H^n \rangle = \frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})H^n(\boldsymbol{R})\Psi_T(\boldsymbol{R})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})}= \mathrm{constant}\times\frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})}=\mathrm{constant}. $$ This gives an important information: the exact wave function leads to zero variance!Variation is then performed by minimizing both the energy and the variance.
For bosons in a harmonic oscillator-like trap we will use is a spherical (S) or an elliptical (E) harmonic trap in one, two and finally three dimensions, with the latter given by
$$ \begin{equation} V_{ext}(\mathbf{r}) = \Bigg\{ \begin{array}{ll} \frac{1}{2}m\omega_{ho}^2r^2 & (S)\\ \strut \frac{1}{2}m[\omega_{ho}^2(x^2+y^2) + \omega_z^2z^2] & (E) \label{trap_eqn} \end{array} \end{equation} $$where (S) stands for symmetric and
$$ \begin{equation} \hat{H} = \sum_i^N \left( \frac{-\hbar^2}{2m} { \bigtriangledown }_{i}^2 + V_{ext}({\bf{r}}_i)\right) + \sum_{i < j}^{N} V_{int}({\bf{r}}_i,{\bf{r}}_j), \label{_auto1} \end{equation} $$as the two-body Hamiltonian of the system.
We will represent the inter-boson interaction by a pairwise, repulsive potential
$$ \begin{equation} V_{int}(|\mathbf{r}_i-\mathbf{r}_j|) = \Bigg\{ \begin{array}{ll} \infty & {|\mathbf{r}_i-\mathbf{r}_j|} \leq {a}\\ 0 & {|\mathbf{r}_i-\mathbf{r}_j|} > {a} \end{array} \label{_auto2} \end{equation} $$where \( a \) is the so-called hard-core diameter of the bosons. Clearly, \( V_{int}(|\mathbf{r}_i-\mathbf{r}_j|) \) is zero if the bosons are separated by a distance \( |\mathbf{r}_i-\mathbf{r}_j| \) greater than \( a \) but infinite if they attempt to come within a distance \( |\mathbf{r}_i-\mathbf{r}_j| \leq a \).
Our trial wave function for the ground state with \( N \) atoms is given by
$$ \begin{equation} \Psi_T(\mathbf{R})=\Psi_T(\mathbf{r}_1, \mathbf{r}_2, \dots \mathbf{r}_N,\alpha,\beta)=\prod_i g(\alpha,\beta,\mathbf{r}_i)\prod_{i < j}f(a,|\mathbf{r}_i-\mathbf{r}_j|), \label{eq:trialwf} \end{equation} $$where \( \alpha \) and \( \beta \) are variational parameters. The single-particle wave function is proportional to the harmonic oscillator function for the ground state
$$ \begin{equation} g(\alpha,\beta,\mathbf{r}_i)= \exp{[-\alpha(x_i^2+y_i^2+\beta z_i^2)]}. \label{_auto3} \end{equation} $$
For spherical traps we have \( \beta = 1 \) and for non-interacting bosons (\( a=0 \)) we have \( \alpha = 1/2a_{ho}^2 \). The correlation wave function is
$$ \begin{equation} f(a,|\mathbf{r}_i-\mathbf{r}_j|)=\Bigg\{ \begin{array}{ll} 0 & {|\mathbf{r}_i-\mathbf{r}_j|} \leq {a}\\ (1-\frac{a}{|\mathbf{r}_i-\mathbf{r}_j|}) & {|\mathbf{r}_i-\mathbf{r}_j|} > {a}. \end{array} \label{_auto4} \end{equation} $$The radial Schroedinger equation for the hydrogen atom can be written as (when we have gotten rid of the first derivative term in the kinetic energy and used \( rR(r)=u(r) \))
$$ -\frac{\hbar^2}{2m}\frac{d^2 u(r)}{d r^2}- \left(\frac{ke^2}{r}-\frac{\hbar^2l(l+1)}{2mr^2}\right)u(r)=Eu(r). $$We will specialize to the case with \( l=0 \) and end up with
$$ -\frac{\hbar^2}{2m}\frac{d^2 u(r)}{d r^2}- \left(\frac{ke^2}{r}\right)u(r)=Eu(r). $$Then we introduce a dimensionless variable \( \rho=r/a \) where \( a \) is a constant with dimension length. Multiplying with \( ma^2/\hbar^2 \) we can rewrite our equations as
$$ -\frac{1}{2}\frac{d^2 u(\rho)}{d \rho^2}- \frac{ke^2ma}{\hbar^2}\frac{u(\rho)}{\rho}-\lambda u(\rho)=0. $$Since \( a \) is just a parameter we choose to set
$$ \frac{ke^2ma}{\hbar^2}=1, $$which leads to \( a=\hbar^2/mke^2 \), better known as the Bohr radius with value \( 0.053 \) nm. Scaling the equations this way does not only render our numerical treatment simpler since we avoid carrying with us all physical parameters, but we obtain also a natural length scale. We will see this again and again. In our discussions below with a harmonic oscillator trap, the natural lentgh scale with be determined by the oscillator frequency, the mass of the particle and \( \hbar \). We have also defined a dimensionless 'energy' \( \lambda = Ema^2/\hbar^2 \). With the rescaled quantities, the ground state energy of the hydrogen atom is \( 1/2 \). The equation we want to solve is now defined by the Hamiltonian
$$ H=-\frac{1}{2}\frac{d^2 }{d \rho^2}-\frac{1}{\rho}. $$As trial wave function we peep now into the analytical solution for the hydrogen atom and use (with \( \alpha \) as a variational parameter)
$$ u_T^{\alpha}(\rho)=\alpha\rho \exp{-(\alpha\rho)}. $$Inserting this wave function into the expression for the local energy \( E_L \) gives
$$ E_L(\rho)=-\frac{1}{\rho}- \frac{\alpha}{2}\left(\alpha-\frac{2}{\rho}\right). $$To have analytical local energies saves us from computing numerically the second derivative, a feature which often increases our numerical expenditure with a factor of three or more. Integratng up the local energy (recall to bring back the PDF in the integration) gives \( \overline{E}[\boldsymbol{\alpha}]=\alpha(\alpha/2-1) \).
We present here another well-known example, the harmonic oscillator in one dimension for one particle. This will also serve the aim of introducing our next model, namely that of interacting electrons in a harmonic oscillator trap.
Here as well, we do have analytical solutions and the energy of the ground state, with \( \hbar=1 \), is \( 1/2\omega \), with \( \omega \) being the oscillator frequency. We use the following trial wave function
$$ \psi_T(x;\alpha) = \exp{-(\frac{1}{2}\alpha^2x^2)}, $$which results in a local energy
$$ \frac{1}{2}\left(\alpha^2+x^2(1-\alpha^4)\right). $$We can compare our numerically calculated energies with the exact energy as function of \( \alpha \)
$$ \overline{E}[\alpha] = \frac{1}{4}\left(\alpha^2+\frac{1}{\alpha^2}\right). $$Similarly, with the above ansatz, we can also compute the exact variance which reads
$$ \sigma^2[\alpha]=\frac{1}{4}\left(1+(1-\alpha^4)^2\frac{3}{4\alpha^4}\right)-\overline{E}^2. $$Our code for computing the energy of the ground state of the harmonic oscillator follows here. We start by defining directories where we store various outputs.
# Common imports
import os
# Where to save the figures and data files
PROJECT_ROOT_DIR = "Results"
FIGURE_ID = "Results/FigureFiles"
DATA_ID = "Results/VMCHarmonic"
if not os.path.exists(PROJECT_ROOT_DIR):
os.mkdir(PROJECT_ROOT_DIR)
if not os.path.exists(FIGURE_ID):
os.makedirs(FIGURE_ID)
if not os.path.exists(DATA_ID):
os.makedirs(DATA_ID)
def image_path(fig_id):
return os.path.join(FIGURE_ID, fig_id)
def data_path(dat_id):
return os.path.join(DATA_ID, dat_id)
def save_fig(fig_id):
plt.savefig(image_path(fig_id) + ".png", format='png')
outfile = open(data_path("VMCHarmonic.dat"),'w')
We proceed with the implementation of the Monte Carlo algorithm but list first the ansatz for the wave function and the expression for the local energy
# VMC for the one-dimensional harmonic oscillator
# Brute force Metropolis, no importance sampling and no energy minimization
from math import exp, sqrt
from random import random, seed
import numpy as np
import matplotlib.pyplot as plt
from decimal import *
# Trial wave function for the Harmonic oscillator in one dimension
def WaveFunction(r,alpha):
return exp(-0.5*alpha*alpha*r*r)
# Local energy for the Harmonic oscillator in one dimension
def LocalEnergy(r,alpha):
return 0.5*r*r*(1-alpha**4) + 0.5*alpha*alpha
Note that in the Metropolis algorithm there is no need to compute the trial wave function, mainly since we are just taking the ratio of two exponentials. It is then from a computational point view, more convenient to compute the argument from the ratio and then calculate the exponential. Here we have refrained from this purely of pedagogical reasons.
# The Monte Carlo sampling with the Metropolis algo
# The jit decorator tells Numba to compile this function.
# The argument types will be inferred by Numba when the function is called.
def MonteCarloSampling():
NumberMCcycles= 100000
StepSize = 1.0
# positions
PositionOld = 0.0
PositionNew = 0.0
# seed for rng generator
seed()
# start variational parameter
alpha = 0.4
for ia in range(MaxVariations):
alpha += .05
AlphaValues[ia] = alpha
energy = energy2 = 0.0
#Initial position
PositionOld = StepSize * (random() - .5)
wfold = WaveFunction(PositionOld,alpha)
#Loop over MC MCcycles
for MCcycle in range(NumberMCcycles):
#Trial position
PositionNew = PositionOld + StepSize*(random() - .5)
wfnew = WaveFunction(PositionNew,alpha)
#Metropolis test to see whether we accept the move
if random() <= wfnew**2 / wfold**2:
PositionOld = PositionNew
wfold = wfnew
DeltaE = LocalEnergy(PositionOld,alpha)
energy += DeltaE
energy2 += DeltaE**2
#We calculate mean, variance and error
energy /= NumberMCcycles
energy2 /= NumberMCcycles
variance = energy2 - energy**2
error = sqrt(variance/NumberMCcycles)
Energies[ia] = energy
Variances[ia] = variance
outfile.write('%f %f %f %f \n' %(alpha,energy,variance,error))
return Energies, AlphaValues, Variances
Finally, the results are presented here with the exact energies and variances as well.
#Here starts the main program with variable declarations
MaxVariations = 20
Energies = np.zeros((MaxVariations))
ExactEnergies = np.zeros((MaxVariations))
ExactVariance = np.zeros((MaxVariations))
Variances = np.zeros((MaxVariations))
AlphaValues = np.zeros(MaxVariations)
(Energies, AlphaValues, Variances) = MonteCarloSampling()
outfile.close()
ExactEnergies = 0.25*(AlphaValues*AlphaValues+1.0/(AlphaValues*AlphaValues))
ExactVariance = 0.25*(1.0+((1.0-AlphaValues**4)**2)*3.0/(4*(AlphaValues**4)))-ExactEnergies*ExactEnergies
#simple subplot
plt.subplot(2, 1, 1)
plt.plot(AlphaValues, Energies, 'o-',AlphaValues, ExactEnergies,'r-')
plt.title('Energy and variance')
plt.ylabel('Dimensionless energy')
plt.subplot(2, 1, 2)
plt.plot(AlphaValues, Variances, '.-',AlphaValues, ExactVariance,'r-')
plt.xlabel(r'$\alpha$', fontsize=15)
plt.ylabel('Variance')
save_fig("VMCHarmonic")
plt.show()
#nice printout with Pandas
import pandas as pd
from pandas import DataFrame
data ={'Alpha':AlphaValues, 'Energy':Energies,'Exact Energy':ExactEnergies,'Variance':Variances,'Exact Variance':ExactVariance,}
frame = pd.DataFrame(data)
print(frame)
For \( \alpha=1 \) we have the exact eigenpairs, as can be deduced from the table here. With \( \omega=1 \), the exact energy is \( 1/2 \) a.u. with zero variance, as it should. We see also that our computed variance follows rather well the exact variance. Increasing the number of Monte Carlo cycles will improve our statistics (try to increase the number of Monte Carlo cycles).
The fact that the variance is exactly equal to zero when \( \alpha=1 \) is that we then have the exact wave function, and the action of the hamiltionan on the wave function
$$ H\psi = \mathrm{constant}\times \psi, $$yields just a constant. The integral which defines various expectation values involving moments of the hamiltonian becomes then
$$ \langle H^n \rangle = \frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})H^n(\boldsymbol{R})\Psi_T(\boldsymbol{R})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})}= \mathrm{constant}\times\frac{\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})} {\int d\boldsymbol{R}\Psi^{\ast}_T(\boldsymbol{R})\Psi_T(\boldsymbol{R})}=\mathrm{constant}. $$ This gives an important information: the exact wave function leads to zero variance!As we will see below, many practitioners perform a minimization on both the energy and the variance.


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object com.threed.jpct.util.ShadowHelper
The ShadowHelper-class eases shadow mapping. While shadow mapping in jPCT is
possible without this helper class, you have to have a good knowledge of how
shadow mapping works in practice to implement it yourself using the methods
that jPCT is offering for it.
To simplify shadow mapping, this helper exists and it should be sufficient
for most shadow applications.
jPCT uses a fixed function approach with depth textures for shadow mapping.
It is advised to initialize this class after enabling the OpenGL renderer
when render-to-texture should be done by using FBOs because otherwise, it's
not known if the hardware actually supports it and the helper has to rely on
the setting in Config alone. The software renderer doesn't support shadow
mapping. It will only cost you performance for no visual benefit when using
this class on a software rendered scene.
Config.glShadowZBias
,
Config.glUseFBO
,
Serialized Form| Constructor Summary | |
ShadowHelper(World world,
FrameBuffer buffer,
Projector lightSource,
int maxSize)
Create a new shadow helper. |
| Method Summary | |
void |
addCaster(Object3D caster)
Adds a caster. |
void |
addReceiver(Object3D rec)
Adds a receiver. |
void |
dispose()
Disposes the helper. |
void |
drawScene()
Draws the scene using the most current shadow map. |
void |
drawScene(boolean complete)
Draws the scene using the most current shadow map. |
void |
finalize()
|
int |
getCasterCount()
Gets the number of casters in the helper. |
Projector |
getLightSource()
Returns the directional light source. |
int |
getReceiverCount()
Gets the number of receivers in the helper. |
Texture |
getShadowMap()
Returns the shadow map's texture. |
boolean |
isInitialized()
Returns true, if the helper has been correctly initialized. |
boolean |
isRenderingShadowMap()
Returns true if, at the time of the call, the helper is working on the shadow map itself. |
boolean |
isRenderingShadowPass()
Returns true if, at the time of the call, the helper is doing the shadow pass. |
void |
removeCaster(Object3D caster)
Removes a caster. |
static void |
resetTextureCounter()
Resets the texture counter. |
void |
setAdditionalColorMode(boolean disabled)
Sets how an objects additional color will be treated. |
void |
setAmbientLight(java.awt.Color col)
Sets the ambient lighting used during the shadow pass. |
void |
setBorder(int width)
Sets a border around the actual shadow map to prevent the shadows from bleeding into parts of the scene that are not covered by the projector's view. |
void |
setCullingMode(boolean inverted)
Sets the culling mode. |
void |
setFiltering(boolean pcf)
Enabled percentage closer filtering on the shadow edges. |
void |
setFrameBuffer(FrameBuffer buffer)
Sets a new FrameBuffer. |
void |
setLightMode(boolean disabled)
Sets the lighting mode. |
void |
setLightSource(Projector lightSource)
Sets the directional light source to another one. |
void |
setRevertMode(boolean mode)
If enabled, every MODE_ADD texture operation will be reverted to a MODE_MODULATE when doing the shadow pass. |
void |
updateShadowMap()
Updates the shadow map as seen from the directional light source. |
| Methods inherited from class java.lang.Object |
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
public ShadowHelper(World world, FrameBuffer buffer, Projector lightSource, int maxSize)
world
- the world that includes the objects to be shadowedbuffer
- the framebuffer into which the world will be renderedlightSource
- the directional light source that casts the shadowsmaxSize
- the maximum size of the shadow map. This isn't necessarily the
used size but an upper bound for it.| Method Detail |
public static void resetTextureCounter()
public Projector getLightSource()
public void setLightSource(Projector lightSource)
lightSource
- the new sourcepublic void setBorder(int width)
width
- public void setFrameBuffer(FrameBuffer buffer)
buffer
- the new FrameBufferpublic void setRevertMode(boolean mode)
mode
- the modepublic void setCullingMode(boolean inverted)
inverted
- should it be inverted?public void setFiltering(boolean pcf)
pcf
- should we use it?public void addReceiver(Object3D rec)
rec
- the receiverpublic boolean isInitialized()
public void addCaster(Object3D caster)
caster
- the new casterpublic void removeCaster(Object3D caster)
caster
- the caster to removepublic void setLightMode(boolean disabled)
disabled
- should the light be disabled during shadow pass? Default is
true.public void setAdditionalColorMode(boolean disabled)
disabled
- should the additional color be disabled during shadow pass?
Default is false.public void setAmbientLight(java.awt.Color col)
col
- the color of the light source. Default is 60,60,60public void drawScene()
public void drawScene(boolean complete)
complete
- if true, everything is rendered. If its false, the last call
to draw() will be omitted (in case you want to do something
else before making it).public boolean isRenderingShadowMap()
public boolean isRenderingShadowPass()
public int getReceiverCount()
public int getCasterCount()
public Texture getShadowMap()
public void updateShadowMap()
public void dispose()
public void finalize()
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


npm install percolator
make test
server.js
in your project directory, and copy this code below into it:var Percolator = require('percolator').Percolator; var server = new Percolator(); server.route('/hello', { GET : function(req, res){ res.object({message : 'Hello World!'}).send(); }}); server.listen(function(err){ console.log('server is listening on port ', server.port); });
Run the server:
node server.js
See your "Hello World" output at http://localhost:3000/hello and be completely floored by the greatest API of all time. Or not.
The output json look like this:{ message: "Hello World!", _links: { parent: { href: "http://localhost:3000/" } } }
You'll notice that Percolator automatically adds a link to the document itself. This is because it tries to help you create a surfable "Hypermedia" API where every endpoint is accessible from a link in another endpoint, and where everything that can be done with the API is described in the API itself.
See the spec for the hyper+json media type for more details on how Percolator outputs its links by default.
Because Hypermedia APIs are pretty awesome for the people using your API.
Developers can find their way to all your endpoints just by following the links in the json payload instead of having to read a bunch of docs.
These types of APIs are machine-readable as well, so they're spider-able, and even allow automatic form generation, or automated fuzz-testing.
In other frameworks adding links everywhere can be time-consuming. Percolator makes this either automatic or very easy though.
NOTE: If you're worried about the size of your responses, keep in mind that with proper caching and compression (gzip), there should be little to no cost to your clients' performance or bandwidth.
If you're still unconvinced, you can just pass autoLink : false
to the
Percolator constructor, and no links will be added automatically.
var server = new Percolator({"some" : "object"});
This is called the app object.
Anything you put in the app object will be available to all your HTTP handlers as req.app, so it's great for shared configuration, database objects, etc.
Additionally, the constructor recognizes a few special properties of the app object:
protocol - 'http' or 'https'
resourcePath - the url path that all the resource will be routed from (eg. Setting it to '/' will serve the
resources from http://yourdomain.com/ while setting it to '/api' will serve the resources from
http://yourdomain.com/api .
staticDir - The directory on the filesystem from which you will serve static content (use an absolute path!).
port - the http port. A low port like 80 will not work unless you run the app with root privileges.
You're obviously going to want to limit the number of app object variables that you add beyond the necessary ones, but certain types of objects might make sense in that shared space.
The route() method of the server takes two parameters, the route string and the resource object.
It then sets a route using the route string that the given handler object will handle when an incoming request matches that route.
Route strings can be regular expressions, or express/sinatra-style route strings.
The resource object is any object that has methods on it that match HTTP methods like POST, PUT, GET, DELETE, etc. The method takes the standard req and res parameters.
The Hello World example above has a resource object that implements only GET:
{ GET : function(req, res){ res.object({message : 'Hello World!'}).send(); } }Of course, other HTTP methods (PUT, POST, DELETE, etc) can be added to this object as well to make this API do more. Here it is, passed to route() with a routeString of '/', the root path:
server.route('/', { GET : function(req, res){ res.object({message : 'Hello World!'}).send(); }});Here it is with a POST handler as well:
server.route('/', { GET : function(req, res){ res.object({message : 'Hello World!'}).send(); }, POST : function(req, res){ req.onJson(function(err, obj){ res.object({posted:obj}).send(); }); } });Note that because resource objects are just objects, you can load them from a file as modules, or create components that you re-use for different modules.
server.listen(function(err){ console.log('server is listening on port ', server.port); });
The before() method takes a callback as its only parameter. The callback is called when a request occurs.
The callback takes req, res, handler and cb parameters.
The req and res parameters are the standard node request and response objects. If you want to augment them for some reason, for all requests, this is a great place to do it.
The handler is the resource object that is routed to the request url in the router. It will contain the functions meant to handle the different HTTP methods.
The cb parameter is a callback that will be called to signal that pre-processing is complete.
Here's an example:
server.before(function(req, res, handler, cb){ // print the request method and url before every request. console.log(' <-- ', req.method, ' ', req.url); cb(); });
The after() method takes a callback as its only parameter. The callback is called after a response is ended.
The callback takes req and res parameters.
The req and res parameters are the standard node request and response objects. If you want to augment them for some reason, for all requests, this is a great place to do it.
Here's an example:
server.after(function(req, res){ // print the request method and url after every request. console.log(' <-- ', req.method, ' ', req.url); });
The connectMiddleware() method takes a connect compatible middleware as its only parameter.
Here's an example:
server.connectMiddleware(connect.favicon()); // add the favicon middleware to the percolator server
The handler object is not an object in the Percolator framework, but rather is one that an application written on the Percolator framework should provide for each route that it defines. It is simply the object that is passed to calls to Server.route() that specifies how a route should handle requests.
It may or may not implement any of the methods listed below. If it does not implement a particular HTTP method, requests to the handler for that method will result in an automatic 405 (method not allowed) response.
Implementing this method on a handler object will allow it to respond to GET requests. The only parameters are the standard request and response objects from node. Any return value will be ignored.
Implementing this method on a handler object will allow it to respond to POST requests. The only parameters are the standard request and response objects from node. Any return value will be ignored.
Implementing this method on a handler object will allow it to respond to DELETE requests. The only parameters are the standard request and response objects from node. Any return value will be ignored.
Implementing this method on a handler object will allow it to respond to PUT requests. The only parameters are the standard request and response objects from node. Any return value will be ignored.
Implementing authenticate() is not required but is convenient if you want to specify a general authentication strategy for all methods on the resource. If you implement authenticate(), it will automatically return 401 responses for unauthenticated access while permitting authenticated access as normal.
The authenticate() function has three required parameters: the standard req and res parameters , and a callback (cb).
The cb argument is a callback that takes two parameters. The first parameter is an error object if any error occurred. If the error object is strictly true, then the response will be a 401. If the error object is non-strict-true but still truthy, then the response will be a 500 (internal server error). The second parameter should be an object that represents the logged in user. It will automatically by added to the req object as req.authenticated in any member resource methods that you implement.
server.route('/someProtectedPath', { authenticate : function(req, res, cb){ // try to get the user here, based on cookie, Authentication header, etc if (cannotGetUser){ return cb(true); // Percolator will 401 for you } cb(someError, theUser); // if there wasn't some other error, theUser will be available // at req.authenticated in all methods }, GET : function(req, res){ res.object({youAre : req.authenticated}).send(); } });
Implementing basicAuthenticate() is not required but is convenient if you want to use basic http authentication on the resource. If you implement basicAuthenticate(), it will automatically return 401 responses for unauthenticated access while permitting authenticated access as normal.
The basicAuthenticate() function has five required parameters: the basic http auth username, the basic http auth password, the standard node req and res objects, and a callback, cb.
The cb argument is a callback that takes two parameters. The first parameter is an error object if any error occurred. If the error object is strictly true, then the response will be a 401. If the error object is non-strict-true but still truthy, then the response will be a 500 (internal server error). The second parameter should be an object that represents the logged in user. It will automatically by added to the req object as req.authenticated in any member resource methods that you implement.
server.route('/someProtectedPath', { basicAuthenticate : function(username, password, req, res, cb){ // try to get the user here, based on cookie, Authentication header, etc if (username === 'Pierre' && password === 'Collateur'){ return cb(null, {username : "Pierre", twitter_handle : "@Percolator"}); // user object will be available in req.authenticated in all methods } else { return cb(true); // Percolator will 401 for you } }, GET : function(req, res){ res.object({youAre : req.authenticated}).send(); } });
Implementing fetch() on a handler object is an unnecessary but sometimes useful way to specify how 404s will be determined, so you don't need to write the same 404-handling code in all methods that you support. If you implement fetch(), fetch can do the 404-ing for you, before your regular handler methods are even run. In the event of a 404, a call to res.status.notFound() will be made automatically.
The fetch() function has three required parameters: the standard node req and res objects, and a callback (cb).
The cb argument is a callback that takes two parameters. The first parameter is an error object if any error occurred. The second parameter should be the object that was fetched from your data source for the current uri. It will automatically by added to the req object as req.fetched in any member resource methods that you implement.
The fetch() function will 404 for you automatically if you pass strict true to the callback ( cb) as the first parameter.
A handler object can also have a boolean property by the name of 'fetchOnPUT' that defaults to true, but allows you to turn fetch off for PUT, even though fetch usually applies to all methods. This is useful if you use PUT for creating new resources at the given URL, because a non-existent resource would otherwise cause a 404.
var module = new CRUDCollection({ fetch : function(req, res, cb){ // get some item from your data source, probably based on req.uri.child() cb(null, theObject); } });
The status module is automatically attached to your resource handler at request time. It is just a bunch of helper functions for dealing with response statuses.
This is an important module because building great APIs requires excellent and consistent error and status reporting.
To understand what the codes mean, please refer to http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
return
in front of it. Here's an example:
server.route('/', { GET : function(req, res){ return res.status.redirect('/someOtherUrl'); }});
Here are the functions that it makes available in your method handler:
"200 OK" statuses are the default, so you don't need to specify those explicitly.
201 Created statuses are described in the redirect section above.
server.route('/', { GET : function(req, res){ return res.status.internalServerError('The server is on fire.'); }});Output:
{"type":500,"message":"Internal Server Error","detail":"The server is on fire"}
{"type":400,"message":"Bad Request"}
{"type":401,"message":"Unauthenticated"}
{"type":403,"message":"Forbidden"}
{"type":404,"message":"Not Found"}
{"type":405,"message":"Method Not Allowed"}
{"type":406,"message":"Not Acceptable"}
{"type":409,"message":"Conflict"}
{"type":410,"message":"Gone"}
{"type":411,"message":"Length Required"}
{"type":412,"message":"Precondition Failed"}
{"type":413,"message":"'Request Entity Too Large"}
{"type":414,"message":"Request URI Too Long"}
{"type":415,"message":"Unsupported Media Type"}
{"type":422,"message":"'Unprocessable Entity"}
{"type":429,"message":"Too Many Requests"}
{"type":500,"message":"Internal Server Error"}
{"type":501,"message":"Not Implemented"}
{"type":502,"message":"Bad Gateway"}
{"type":504,"message":"Gateway Timeout"}
Each method you define has access to a 'uri' object instantiated from the uri of the current request. The uri object has a chainable/fluent interface that makes a number of methods available for for querying different aspects the current uri, and even modifying it to create new uris.
Most methods are named after different parts of the uri and allow you to read that part from the current uri if you don't pass any parameters, or they allow you to generate a new uri with a change to that part in the current uri if you do pass a parameter.
For the examples below, we'll use the following uri:
https://user:pass@subdomain.asdf.com/path/kid?asdf=1234#fragHere are example usages:
server.route('/', { GET : function(req, res){ res.object({self : req.uri}).send(); // --> {"self" : "http://example.com/currentUrl"} }});
req.uri.child(); // returns "kid" req.uri.child("grandkid"); // returns a new uri object with the uri // https://user:pass@subdomain.asdf.com/path/kid/grandkid?asdf=1234#fragsee also: req.uri.parent(), req.uri.path().
req.uri.decode('this%20is%20a%20test'); // returns "this is a test"see also: req.uri.encode().
req.uri.encode('this is a test'); // returns 'this%20is%20a%20test'see also: req.uri.decode().
req.uri.hash(); // returns 'frag' req.uri.hash("blah"); // returns a new uri object with the uri // https://user:pass@subdomain.asdf.com/path/kid/?asdf=1234#blah
req.uri.hostname(); // returns 'subdomain.asdf.com' req.uri.hostname("geocities.com"); // returns a new uri object with the uri // https://user:pass@geocities.com/path/kid/?asdf=1234#frag
req.uri.parent(); // returns a new uri object with the uri // https://user:pass@subdomain.asdf.com/path/?asdf=1234#fragsee also: req.uri.child(), req.uri.path().
req.uri.password(); // returns 'pass' req.uri.password("newpass"); // returns a new uri object with the uri // https://user:newpass@subdomain.asdf.com/path/kid/?asdf=1234#fragsee also: req.uri.username(),
req.uri.path(); // returns '/path/kid' req.uri.path("newpath"); // returns a new uri object with the uri //<EMAIL_ADDRESS>// ALSO, req.uri.path() can take arrays of strings as input as well: req.uri.path(['qwer', '/asdf'], 'qwer/1234/', '/1234/'); // this returns a new uri object with the uri //<EMAIL_ADDRESS>Note: changing the path will remove the querystring and hash, since they rarely make sense on a new path.
see also: req.uri.child(), req.uri.parent().req.uri.port(); // returns 80 req.uri.port(8080); // returns a new uri object with the uri // https://user:pass@subdomain.asdf.com:8080/path/kid/?asdf=1234#frag
req.uri.protocol(); // returns 'https' req.uri.protocol("http"); // returns a new uri object with the uri // http://user:pass@subdomain.asdf.com/path/kid/?asdf=1234#frag
req.uri.query(); // returns {asdf : 1234} req.uri.query(false); // returns a new uri object with the querystring-free uri //<EMAIL_ADDRESS>req.uri.query({spaced : 'space test'}) // returns a new uri object with the input object serialized // and merged into the querystring like so: // https://user:pass@subdomain.asdf.com/path/kid/?asdf=1234&spaced=space%20test#frag
NOTE: escaping and unescaping of applicable characters happens automatically. (eg " " to "%20", and vice versa)
NOTE: an input object will overwrite an existing querystring where they have the same names.
NOTE: an input object will remove an existing name-value pair where they have the same names and the value in the input name-value pair is null.
see also: req.uri.queryString(),
req.uri.queryString(); // returns asdf=1234 (notice there is no leading '?') req.uri.queryString("blah"); // returns a new uri object with a new querystring // https://user:pass@subdomain.asdf.com/path/kid?blah#frag
NOTE: no escaping/unescaping of applicable characters will occur. This must be done manually.
see also: req.uri.query(),
req.uri.toJson(); // returns // "https://user:pass@subdomain.asdf.com/path/kid/?asdf=1234#frag"
req.uri.toString(); // returns // "https://user:pass@subdomain.asdf.com/path/kid/?asdf=1234#frag"
req.uri.username(); // returns 'user' req.uri.username("newuser"); // returns a new uri object with the uri // https://newuser:pass@subdomain.asdf.com/path/kid/?asdf=1234#fragsee also: req.uri.password(),
res.object({some : "test"}).toString(); // returns '{"some":"test"}'
res.object({some : "test"}).toObject(); // returns {some:"test"}
res.object({some : "test"}).property("also", "this").toObject(); // returns {some:"test",also:"this"}
res.object({some : "test"}).link("somerel", "http://some.example.com").toObject(); // returns {some:"test",_links:{somerel:{href:"http://some.example.com"}}}
res.object({some : "test"}).link("somerel", "http://some.example.com", {method:"POST", schema:{}}).toObject(); // returns {some:"test",_links:{somerel:{href:"http://some.example.com",method:"POST",schema:{}}}}
res.object({some : "test"}).send();
// object/hash version res.collection({someitem : "1234",someotheritem : 4567}).toObject(); // returns: { _items : { someitem : "1234", someotheritem : "4567" }, _links : { parent: { href: "http://example.com/api" } } }
// array version res.collection([{someitem : "1234"},{someotheritem : 4567}]).toObject(); // returns: { _items : [ {someitem : "1234"}, {someotheritem : "4567"} ], _links : { parent: { href: "http://example.com/api" } } }
res.collection({some : "test"}).each(function(item){return item + "2";}).toObject(); // returns... { _items : { some: "test2" }, _links : { parent: { href: "http://example.com/api" } } }
res.collection([{some:"test"}]).each(function(item){return item + "2";}).toObject(); // returns... { _items : [ { some: "test2" } ], _links : { parent: { href: "http://example.com/api" } } }
res.collection({some : "test"}).linkEach('plustwo', function(item){return 'http://server.com/' + item + "2";}).toObject(); // returns... { _items : { some: "test", _links : { plustwo : { href : 'http://server.com/test2' } } }, _links : { parent: { href: "http://example.com/api" } } }
res.collection([{some : "test"}]).linkEach('plustwo', function(item){return 'http://server.com/' + item['some'] + "2";}).toObject(); // returns... { _items : [ some: "test", _links : { plustwo : { href : 'http://server.com/test2' } } ], _links : { parent: { href: "http://example.com/api" } } }
req.onJson() is used for handling a request where the request body is json (normally a PUT or POST). It takes care of accepting the incoming stream, attempting to parse it to json, and automatically sending a 400 error if it does not parse.
The first, optional parameter, schema, is a json schema as a javascript object (not as a string). This schema object can be used to validate the incoming json object if desired. req.onJson will return an appropriate error to the user if the incoming json is not acceptable according to the schema.
The last (or only) parameter is a callback that is used if the incoming json parses successfully. The callback will take an 'error' and an 'object' parameter, where the error parameter will contain any error that was not automatically handled (like a network error), and the object parameter will contain any object that was deserialized from the incoming json (if possible).
// without a json schema... req.onJson(function(err, obj){ console.log('error: ', err); console.log('object: ', obj); });
// with a json schema... var schema = { properties : { "username" : { type : "string", required : true } }; req.onJson(schema, function(err, obj){ console.log('error: ', err); console.log('object: ', obj); });
req.onBody() is used for handling the streaming of non-json request bodies.
The only parameter is a callback that takes an error and a body parameter. The error parameter will be null unless an error occurred during streaming of the body, in which case it will contain the error. The body parameter will contain the request body as a string for use inside the callback.
req.onBody(function(err, body){ console.log('error: ', err); console.log('body: ', body); // body is just a string here });
NOTE: If you're expecting json, then you should normally use req.onJson() instead of this method.
A CRUDCollection is a module that implements handlers for a json collection, and all its members. It allows you to implement just your CRUD (create, read, update, delete) logic for the collection and its members without having to deal with much HTTP/API logic at all.
Here's how it's constructed:
var CRUDCollection = require('percolator').CRUDCollection; var module = new CRUDCollection({ // implementation strategy goes here! });
The module that is created will have two properties: handler and member. The handler property is a handler for a collection and can just be routed like this:
server.route('/myCollection', module.handler);
The wildcard property is a handler for the members of the collection and can be routed like this:
server.route('/myCollection/:memberid', module.wildcard);
Implement the list() function to provide the module with all the items that should show up in the collections GET view. CRUDCollection requires that either this function or collectionGET() is implemented to ensure that your collection is accessible via GET.
var module = new CRUDCollection({ list : function(req, res, cb){ // generate the list to return for the collection view. cb(null, [{some : "object"}, {some : "otherobject"}]); } });
Implement the fetch() function to provide the GET handler for individual members of the collection. If you don't implement this, you'll need to implement memberGET() to be able to GET resources for individual members.
The fetch() function has three required parameters: the standard node req and res objects, and cb.
The cb argument is a callback that takes two parameters. The first parameter is an error object if any error occurred. The second parameter should be the object that was fetched from your data source for the current uri. It will automatically by added to the req object as req.fetched in any member resource methods that you implement.
The fetch() function will 404 for you automatically if you pass strict true to the callback ( cb) as the first parameter.
This function is also used for automatically determining if it should 404 for PUTs and DELETEs to the individual members as well.
var module = new CRUDCollection({ fetch : function(req, res, cb){ // get some item from your data source, probably based on req.uri.child() cb(null, theObject); } });
The create() function is used for creating new resources via POST to the collection when the unique ID for the user (and its URI in general) are server-generated and NOT client-provided.
Implement create() to allow this kind of object creation. The CRUDCollection will do json parsing and validation for you (if you supply a schema or a createSchema ) and it will respond with appropriate error messages automatically in the case of failures.
The function will be passed the standard node req and res objects, the unserialized json object, and a callback. The callback takes no parameters and can optionally be called in the event of successful creation to respond with a 201 CREATED status. You have the option of not calling the callback at all and instead responding however you want.
var module = new CRUDCollection({ create : function(req, res, object, cb){ // store your object here cb(); } });
The update() function is used for updating existing resources via PUT to the individual resource's existing URI.
Implement update() to allow resources to be updated. The CRUDCollection will handle the json parsing and validation for you ( if you supply a schema or an updateSchema) and it will respond with appropriate error messages automatically in the case of failures.
The function will be passed the standard node req and res objects, the 'id' at the
end of the resource's URI, the object returned from
fetch()
, and a callback. The callback takes
no parameters and can optionally be called in the event of
successful update to respond with a 303 redirect. You have
the option of not calling the callback at all and instead
responding however you want.
var module = new CRUDCollection({ update : function(req, res, id, obj, cb){ // update your object here cb(); }; });
In general, "upsert" is short for "update if existing, and insert if not already existing".
The upsert() function is used for updating existing resources or creating resources if they don't already exist via PUT to the individual resource's URI. If the URI already exists, the resource there will be updated. If the URI doesn't already exist, the resource there will be created. You would use upsert() when the unique ID and URI of the resource is determined by the client and is NOT server-generated.
Implement upsert() to allow resources to be upserted. The CRUDCollection will handle the json parsing and validation for you ( if you supply a schema or both updateSchema AND createSchema ) and it will respond with appropriate error messages automatically in the case of failures.
The function will be passed the standard node req and res objects, the 'id' at the
end of the resource's URI, the object returned from
fetch()
, and a callback. The callback takes
no parameters and can optionally be called in the event of
successful 'upsertion' to respond with a 303 redirect. You have
the option of not calling the callback at all and instead
responding however you want.
var module = new CRUDCollection({ upsert : function(req, res, id, obj, cb){ // upsert your object here cb(); }; });
The destroy() function is used for removing existing resources via DELETE to the individual resource's URI. If the URI already exists, the resource there will be removed. If the URI doesn't exist, CRUDCollection will automatically respond with a 404 NOT FOUND status.
Implement destroy() to allow resources to be removed.
The function will be passed the standard node req and res objects, the 'id' at the end of the resource's URI, and a callback. The callback takes no parameters and can optionally be called in the event of successful 'removal' to respond with a 204 to indicate a success with no response body. You have the option of not calling the callback at all and instead responding however you want.
var module = new CRUDCollection({ destroy : function(req, res, id, cb){ // remove your object here cb(); }; });
The collectionGET() function is a way of completely handling the GET for the collection resource if you don't want the automatic handling that list() provides. This usually shouldn't be necessary. Also note that this is basically just an alias for crudCollection.handler.GET.
var module = new CRUDCollection({ collectionGET : function(req, res){ res.object({"make":"your own response"}).send(); }; });
The memberGET() function is a way of completely handling the GET for member resources (items in the collection) if you don't want the automatic handling that fetch() provides. This usually shouldn't be necessary. Also note that this is basically just an alias for crudCollection.wildcard.GET.
var module = new CRUDCollection({ memberGET : function(req, res){ res.object({"make":"your own response"}).send(); }; });
The updateSchema property is a way to specify a json schema object that will be used to validate json used for updating the resource. If you want the same validation for creating the resource as you want for updating it, you can just use the schema property instead.
The updateSchema object will also be used in the update link for the individual collection member resource to show developers and machines how an update is validated.
The createSchema property is a way to specify a json schema object that will be used to validate json used for creating a resource. If you want the same validation for creating the resource as you want for updating it, you can just use the schema property instead.
The createSchema object will also be used in the create link in the collection resource to show developers and machines how a create (POST) is validated.
The schema property is a way to specify a json schema object that will be used to validate json used for creating or updating a resource. If you want different validations for creating the resource than you do for updating it, you can use the specific createSchema and updateSchema properties instead.
The schema object will also be used in the create link in the collection resource and the update link in the individual collection member resource to show developers and machines how creates and updates are validated.
Percolator also allows a more advanced style of routing that lets you load your route-handling resources from external files instead.
./resources/index.js
. (First create a resources
directory and
then the index.js
file in it, and then copying the handler logic into
index.js
like so:exports.handler = { GET : function(req, res){ res.object({message : 'Hello World!'}).send(); } }We'll call files like that "resources" from now on.
routeDirectory()
instead of server.route()
like so:var Percolator = require('Percolator'); var server = new Percolator(); server.routeDirectory(__dirname + '/resources', '/api', function(err){ if (!!err) {console.log(err);} server.listen(function(err){ console.log('server is listening on port ', server.port); }); });
Run the server:
node server.js
See your "Hello World" output at http://localhost:3000/api . You should see the same output as the original "Hello World" example.
This worked because index.js is the reserved filename for responding to '/'. If you want to respond
to uris like '/hello', you can simply drop a hello.js
in that folder (that exports a
similar handler) and it will respond to http://localhost:3000/api/hello . The advantage to this way
of routing is that all your resources can be in separate files so that your project can be more easily
organized.


announcement of a new discipline: paleo-bio-socio-psychology
From Howard<EMAIL_ADDRESS>Organization BIOSCI International Newsgroups for Molecular Biology
Date 2 Jun 1997 05:19:49 -0700
Newsgroups bionet.biology.symbiosis
Message-ID<EMAIL_ADDRESS>We have started a new
discipline--paleo-bio-socio-psychology or paleopsychology for
short. The enclosed manifesto was written at the request of the
Journal of the Across Species Comparisons and Psychopathology
Society. We hope you find it of some interest.
------------------------
MANIFESTO FOR A NEW PSYCHOLOGICAL SCIENCE
by
Howard Bloom
(member: New York Academy of Sciences, American Association
for the Advancement of Science, American Psychological
Society, Academy of Political Science,
Human Behavior and Evolution Society, European
Sociobiological Society)
My collaborators and I propose the establishment of a new
discipline: paleo-bio-socio-psychology or "paleopsychology" for
short. Each of us has already taken initial steps toward creating
a corpus of paleopsychological knowledge. We welcome those who
would like to join us.
Standard paleontology has done a magnificent job of recreating the
morphology of creatures ranging from the first life forms 3.85
billion years ago to the early humans of comparatively recent
times. In the case of the majority of pre-historic species,
however, paleontology has left us with a considerable problem. How
did these creatures behave? What, if any, were their social
patterns? What cognitive and problem-solving abilities did they
possess? What was the bio-evolutionary sequence which led to
learning, imitation, herding, information sharing, and to what John
Tyler Bonner has called animal culture?
Primate fossil evidence has often been looked at with an eye to
inferring the origins of campsites, tools, migratory patterns,
"mental modules," and some of the subject matter of which
paleopsychology is made. Similarly, dinosaur remains have been
scrutinized for signs of maternal nurturance and other indicators
of social attachment and of the ability to tell one conspecific
from another. But what of the social interactions and reactive
powers of the earliest bacteria, the first eukaryotes, the
recently-discovered Precambrian clams, and the Cambrian profusion
of phyletic representatives--from trilobites to eurypterids?
What about the first insects of 350 mya--were they initially
solitary, as E.O. Wilson and numerous others assume, or were they
social, as one of us suspects? Was individuality or sociality the
original state of living beings? If the latter, how did the
anomaly of solitary existence emerge? If the former, where does
sociality begin in the fossil record, and why?
The tools with which these questions can be probed are few today,
but will surely expand as more minds join the quest. Mass-
behavior-specialist Howard Bloom has used data on bacterial social
behavior along with fossil evidence to postulate that the
cyanobacteria of 3.5 billion years ago were not only
extraordinarily social, but that their colonies exhibited what
physicist-turned-microbiologist Eshel ben Jacob calls a collective
"creative" intelligence. Extrapolating from the work of Sorin
Sonea and Maurice Panisset (1983), Bloom has gone on to make the
case that the Pre-cambrian system of prokaryotic information
exchange was literally worldwide. In addition, Bloom has penned
four papers for Germany's Telepolis tracing the history of the
cooperative impulse and of cognitive development from the first
10(-32) second of the Big Bang to 35 million b.p. Combined with
the data of Ben Jacob and of the University of Chicago's James
Shapiro, Bloom's published views call into question fundamental
axioms of neo-Darwinist evolutionary theory.
Invertebrate zoologist Kerry B. Clark, creator of the definitive
teaching CD-ROM Metazoa, has applied the rules of his field to the
fossil record, tentatively recreating Cambrian social behavior.
Among other things, he hypothesizes that Anomalocaris canadensis
swam in feeding herds. "The largest animals in most ecosystems are
typically herding herbivores," he notes, "and I see nothing about
Anomalocaris that precludes this."
Paleontologist Kevin Brett, who spent five years working at the
Burgess Shale for the Royal Ontario Museum under the sponsorship of
National Geographic Magazine, disagrees about Anomalocaris, but
cites evidence that trilobites may well have been sexually
dimorphic, and that many trilobites were, in his words, "quite
ornate." Brett also points to the well-known observation that,
"Trilobites are often found in mass associations of mono-specific
gatherings of complete individuals. This suggests mating and/or
moulting gatherings such as those observed in modern marine
arthropods such as Limulus (Horseshoe crabs). Evidence has been
found for multispecific gatherings as well as physical processes
such as wave and current transport." From this and the positioning
of trilobites in fossil beds, he proposes that trilobite sexual
gatherings may not have been entirely promiscuous. Modern "toads,"
he points out, "will mate with just about anything--so they don't
necessarily recognize members of even their own species." Brett
suspects that Cambrian arthropods were more discerning.
Entomologist Christine Nalepa cites an understudied source of data,
trace fossils. From fecal remains in chambers carved in dead
Carboniferous tree ferns, she infers that the earliest proto-
cockroaches (Cryptocercidae-like insects) may have shown active
social behavior 300 million years ago--over 160 million years
before even the most extreme dates hypothesized for the emergence
of eusociality.
As Brett points out, "All animals are social. We have the
opportunity to trace the degrees of sociality in the fossil record
using burrow and hive traces, mass associations, nests, etc." Adds
Clark, "The chemical transmitters in the most advanced organisms
have their precursors in the simple biochemically-mediated
behavioral responses of bacteria and protists, indicating a
continuity of mechanisms between these extremes.
"The basic organizational features of the most advanced nervous
systems -- ganglionation, condensation of diffuse sensors into
discrete organs, and interneuronal processing -- that we associate
with intelligent behavior, are expressed in all but the simplest
animals, and it is reasonable to look for, and expect, some
expression of intelligent behaviors in 'lower' animals. Social
behaviors, by assembling superorganisms, facilitate 'emergent
properties' that can assemble intelligent behaviors not found in
solitary forms, optimizing exploitation of their environments, and
may or may not be associated with fossil evidence of the
superorganism. The two prime correlates of intelligence, organism
size and complexity, can arise both in big, complex individuals and
in smaller organisms that communally form large, complex units of
biomass. Our knowledge and recognition of such social interactions
is still at an early stage."
Bloom, Clark, Brett and Nalepa are all members of our group. But
we have illustrious forebears. Charles Darwin hinted at a
psychology of the creatures which preceded us in his Expression of
Emotions in Man and Animals (1872). With Darwin's blessings,
George Romanes took the query a step further in his 1884 Mental
Evolution In Animals. Lynn Margulis has done a masterful job of
reconstructing the lives of what she calls "microbial communities
in the Archean and Proterozoic Eons." Margulis credits as other
predecessors Schimper (in his work of 1833), Famintzyn (1891),
Mereschkovsky (1909), Portier (1918) and Wallin (1927)--all
concerned, as is Margulis, with evolutionary cell biology. In
addition, B. Moore has worked recently on reconstructing the
evolution of imitative learning.
Yet the area explored by these pioneers has often been forgotten
once the researchers responsible have gone. It is time to end this
periodic amnesia. The tools exist. The evidence exists. And the
need to know is there. The evolution of behavior, sociality, and
the physiology of proto-mentation finally deserve a discipline of
their own.
If you wish more information on paleopsychology, or would like to
join us in our quest, please e-mail or phone:
Howard Bloom
705 President Street
Brooklyn, NY 11215
phone<PHONE_NUMBER>
fax<PHONE_NUMBER>
e-mail<EMAIL_ADDRESS>For further data on the participants and a taste of their
accomplishments, see: www.bookworld.com/lucifer (re Howard Bloom);
http://users.aol.com/kbclark/cambrian and
http://users.aol.com/kbclark/metahome (Dr. Kerry B. Clark);
www.ualberta.ca/~kbrett/Trilobites.html and
www.ualberta.ca/~kbrett/index.html (re Kevin Brett); and Nalepa,
Christine (1994), "Nourishment and the Origin of Termite
Eusociality," in Nourishment and Evolution in Insect Societies,
edited by James H. Hunt and Christine A. Nalepa, 1994, Boulder,
Colorado: Westview Press: 57-96.
--------------------------------------------
Things are moving so rapidly that despite a month of 7
AM to 4:30 AM workdays, I am having trouble keeping up with them.
1) Telepolis Magazine, a german web publication from the Heise
publishing house, has offered to do two things. It is already
printing the chapters of my book outlining twelve billion years of
paleopsychology, and will do so until that book's completion. It
has also made available to our group--now called The International
Paleopsychology Project--an "open forum" in which members may
advance their ideas. These will be targeted essays by major
scientists (of which we have many--there are roughly 40 of us now),
each adding a piece to a twelve-billion-year mosaic.
2) My agent, Richard Curtis, president of the Association of
Author's Representatives, wants our key members each to conceive a
book for the mass audience, a work along the lines of "The Selfish
Gene" or "The Lives of a Cell"--presenting important new ideas but
in a manner any intelligent person can understand and even relish.
I will act as executive editor. Each work must not only surprise
with its insights, but must contribute to the mosaic we are
creating, one based on a very new scientific worldview. Some
members may simply add to the paleopsychology timeline. Others are
activists in a secondary goal for which I've been gathering
researchers from around the world these last two years--the
proposal of a post-neo-Darwinian paradigm, one which does for
current evolutionary theory what Relativity did for Newtonianism.
The goal is not to negate the highly productive concepts of the
past, but to demonstrate the sphere within which they belong, then
stretch out to encompass the universe of empirical data which the
old ideas cannot embrace. Our first book is likely to be from
Eshel Ben Jacob, whose papers in Nature, Physica A, Contemporary
Physics and others over the last seven years have given both the
evidence and theory for a leap the physicist/microbiologist calls
"orthogonal to Darwinism." My own book offering a post
neo-Darwinian vision will also be a part of the series. And
proposals are now flowing in from other group members. Please
increase the rate of that flow if you can. Our agent is chomping
at the bit to take a complete package of book proposals to the top
execs at the major publishing houses.
3) There is talk--just talk, but serious talk indeed--of an
International Paleopsychology Project gathering. We shall see if
this comes to fruition. Could anyone who might be able to
contribute to the creation of such a thing contact me, and I will
put him in touch with the person who is crafting this effort.
4) One of our computer scientists, Alexander Chislenko, is on the
verge of doing an independent project at MIT under the aegis of
Marvin Minsky which will parallel Howard Bloom's exploration of the
history of information pooling, but do so in terms of information
theory. Chislenko will then extrapolate from the past and project
future possibilities of the collective intelligence through the
growth of symbiotic forms of wide-scale human/machine cooperation
models and distributed artificial intelligence. The technological
part of the project will involve designing cooperative knowledge
sharing network as an active intelligent extension to today's World
Wide Web. Information on Chislenko's writings and projects is
available on-line at
5) Our present e-mail center will gradually become a laboratory for
virtual collaboration, more project than chat oriented. But this
will take time. Even the best of labs cease their productivity
when their lunchrooms are shuttered and informal conversation ends.
So we must achieve a balance.
I hope this gives you at least an idea of our momentum since we
first went public with four scientists on April 18th.
As of Sunday April 27 at 4:00 PM, the group organized around
paleopsychology consisted of the following members (in the ensuing
weeks, 26 more have joined, some of them illustrious in the world
of science; they will be announced in further correspondence):
The work of Tel-Aviv University's Eshel ben Jacob--a
physicist-turned-microbiologist--on bacterial "creative webs" is
paradigm breaking. In a paper to be published momentarily by
Physica A, "Bacterial Wisdom, Godel's Theorem and Creative Genomic
Webs," Dr. Ben Jacob challenges the roots of current neo-Darwinism.
Ben Jacob's studies of bacterial colony formation have appeared
with great regularity in Contemporary Physics, Nature, Fractals,
Physical Review Letters, Physical Review E, etc. In addition he is
co-editor of "The Physics of Biological Systems: from molecules to
species," Berlin, Springer, 1997. His contribution to this book is
entitled "Smart Bacterial Colonies." Ben-Jacob's "Cooperative
formation of bacterial colonies" appears in "Bacteria as
Multicellular Organisms," edited by J.A. Shapiro and M. Dwarkin,
Oxford: Oxford University Press, 1997.
Howard Bloom is a member of the New York Academy of Sciences,
American Association for the Advancement of Science, American
Psychological Society, Academy of Political Science, Human Behavior
and Evolution Society, European Sociobiological Society, and has
lectured at Wesleyan University, Georgia State University, CUNY,
and New York University. As a mass-behavior-specialist, Bloom has
used data on bacterial social behavior along with fossil evidence
to postulate that the cyanobacteria of 3.5 billion years ago were
not only social, but that their colonies exhibited what
Eshel ben Jacob calls a collective "creative" intelligence. In
addition, Bloom has penned four papers for Germany's Telepolis
tracing the history of the cooperative
impulse and of cognitive and proto-memetic development from the
first 10(-32) second of the Big Bang to 35 mya. Bloom's work calls
into question fundamental axioms of neo-Darwinist evolutionary
theory. All this is the culmination of a research agenda Mr. Bloom
undertook in 1956. Bloom has been aiming at a post-neo-Darwinian
synthesis since 1981. More recently, Bloom was the only scientist
asked to organize a panel at the 1996 Annual Meeting of the
European Sociobiological Society. He has been featured in every
edition of "Who's Who in Science and Engineering" since the
publication's inception. In 1995, Bloom founded an informal
academic circle called "the group selection squad," whose efforts
helped re-legitimate the discussion of group selection within the
evolutionary community. Mr. Bloom's book, "The Lucifer Principle:
a scientific expedition into the forces of history" (New York:
Atlantic Monthly Press, 1995) has been called "A revolutionary
vision of the relationship between psychology and history"
(Elizabeth F. Loftus, Professor of Psychology, University of
Washington, author of Memory and Eyewitness Testimony); "a long
step forward in the human effort to understand human biology" (Dr.
Richard Bergland, M.D., researcher on brain endocrinology, founder
of the department of neurosurgery, Sloan/Kettering, author of "The
Fabric of Mind"); and "a freshly viable theory of human social
evolution" (The Washington Times).
Paleontologist Kevin Brett, of the Department of Earth and
Atmospheric Sciences, University of Alberta, Canada, spent five
years working at the Burgess Shale for the Royal Ontario Museum
under the sponsorship of National Geographic Magazine. Brett's
experience with trilobites and other Paleozoic fossils both in the
field and in the lab is extensive. He is currently engaged in Ph.D.
research on Devonian trilobites and maintains the leading trilobite
site on the WWW. His fieldwork has covered nearly all of Canada,
most of the eastern USA, and Morocco. Brett explains that his
"love and experience with trilobites started when I could crawl."
He fails to mention that by the time he began his crawling, the
trilobites had ended theirs.
Invertebrate zoologist Kerry B. Clark, creator of the definitive
teaching CD-ROM "Metazoa(tm)," has applied the rules of his field
to the fossil record, graphically recreating Paleozoic social
behavior. One result has been the visually and informationally
stunning CD-Rom "Metazoa," designed for museum and educational use.
Dr. Clark is Professor of Biological Sciences at the Florida
Institute of Technology. He says, "My research interests include
all aspects of the biology of opisthobranch gastropod molluscs
(sea slugs); physiological and population ecology; conservation of
marine invertebrates; and computer applications in biology."
NYU neurophysiologist Edgar E. Coons, leads a "laboratory devoted
to studying drive and hedonic mechanisms in the brain and how they
interact." Dr. Coons is the discoverer of lateral hypothalamic
stimulation's ability to elicit feeding, ameliorate anxiety, and
lower pain in rats. He has been published in Science, The Annals
of the New York Academy of Sciences, Brain Research, Behavioral
Neuroscience and the Journal of Comparative and Physiological
Psychology, among others.
The Director of Palo Alto's Institute for the Study of Complex
Systems, Dr. Peter Corning is author of "The Synergism Hypothesis"
(New York: McGraw Hill, 1983) and the upcoming "Holistic
Darwinism" -- now in press at the Journal of Social and
Evolutionary Systems. He writes, "I taught in the interdisciplinary
Human Biology Program at Stanford for seven years and held a
research appointment in Stanford's interdisciplinary
Engineering-Economic Systems Department. I also spent two years on
an NIMH post-doctoral research fellowship at the Institute for
Behavioral Genetics (University of Colorado) and published
laboratory experimental work on the genetics of aggression. More
recently, I was a fellow at the Collegium Budapest (Institute for
Advanced Study) in Hungary. I have also published three books (two
on synergy) and, frankly, an uncounted number of articles."
The University of Ghent's Koen DePryck is author of:"Knowledge,
evolution and paradox: the ontology of language," SUNY Press; of
the forthcoming "Possible evolutionary advantages of learning
difficulties"; and creator of a larger project called "the
archeology of mind".
Columbia University's Ralph Holloway, a Fellow of the New York
Academy of Sciences and the AAAS, was involved in the landmark work
by Marion Diamond et. al. demonstrating the relationship of
dendritic branching to stimulus in rats. His major areas of
concentration are sexual dimorphism in the human and chimpanzee
corpus callosum, and paleoneurology. He says, "I've made many of
the brain endocasts of our fossil ancestors from Africa, and have
traveled there as well as Indonesia and Europe to endocast the
crania....I tend to believe that careful analyses of stone
toolmaking is our best bet for probing hominid cognition, a view
I've been too rigid to let go since my 1969 'Culture: A Human
Domain' paper in Current Anthropology. I also have an interest in
aggression, and even edited a book on it in 1974."
David Smillie functioned as a developmental psychologist for forty
years and spent the last twenty five of those years as a professor
at New College, University of South Florida. Since 1993 he has
been a visiting professor in the Department of Zoology at Duke
University where he has been pursuing a study, begun twenty five
years ago, of social evolution. He has published articles on both
these fields in a variety of journals and books.
--------------------------------------
to join or to obtain further information contact
Howard Bloom
(member: New York Academy of Sciences, American Association for the
Advancement of Science, American Psychological Society, Academy of
Political Science, Human Behavior and Evolution Society, European
Sociobiological Society)
705 President Street
Brooklyn, NY 11215
phone<PHONE_NUMBER>
fax<PHONE_NUMBER>
e-mail<EMAIL_ADDRESS>for two chapters from
The Lucifer Principle: A Scientific Expedition Into the Forces of
History,
see www.bookworld.com/lucifer
The Lucifer Principle:a
scientific expedition into the forces of history


{% extends "base.html" %} {% load crispy_forms_tags %} {% block title %} {{ block.super }} - Profile Search {% endblock title %} {% block nav-user-classes %}active{% endblock nav-user-classes %} {% block content %}
Do you know if you already have a profile at Women in Neuroscience? Use the form below to check it out.
{{ profile.position }}
{{ profile.institution }}
{{ profile.country }}
No matching profiles.
Cannot find your profile?
Create a new profile


You need to enable JavaScript to run this app.
MAP
Sorry, your browser does not support HTML5 video.


The XQC_ErrorHandler struct is designed to be populated by users for the purpose of collecting more detailed error messages from an XQC implementation. More...
#include <xqc.h>
Public Attributes | |
| void * | user_data |
| Can be used for user specific purposes. | |
| void(* | error )(XQC_ErrorHandler *handler, XQC_Error error, const char *error_uri, const char *error_localname, const char *description, XQC_Sequence *error_object) |
| The function called when an error occurs. |
The XQC_ErrorHandler struct is designed to be populated by users for the purpose of collecting more detailed error messages from an XQC implementation.
An XQC_ErrorHandler can be set for a query execution using the XQC_StaticContext::set_error_handler() and XQC_DynamicContext::set_error_handler() functions.
The XQC_ErrorHandler struct has no free() function pointer because the user remains responsible for freeing the resources associated with this struct.
| void(* XQC_ErrorHandler_s::error)(XQC_ErrorHandler *handler, XQC_Error error, const char *error_uri, const char *error_localname, const char *description, XQC_Sequence *error_object) |
The function called when an error occurs.
The function receives the components of the error as arguments. When this function returns, the implementation will exit query preparation or execution with the error enumeration value passed as an argument.
| handler | The XQC_ErrorHandler that this function pointer is a member of | |
| error | An enumeration value representing the type of error. One of either XQC_STATIC_ERROR, XQC_TYPE_ERROR, XQC_DYNAMIC_ERROR, or XQC_SERIALIZATION_ERROR. | |
| error_uri | The namespace URI of the error code QName as a UTF-8 string, or 0 if there is no namespace URI. | |
| error_localname | The local name of the error code QName as a UTF-8 string. | |
| description | The description of the error message as a UTF-8 string. The description may be absent, in which case this parameter will be 0. | |
| error_object | The error object, potentially passed to the fn:error() function. The user owns this object, and is responsible for freeing it. The error_object may be absent, in which case this parameter will be 0. Some implementations may not provide this functionality, meaning that this parameter will always be 0. |
Can be used for user specific purposes.


<EMAIL_ADDRESS>const charCodes = [115, null, 104, 105, 116]
let result = ''
for (let i = 0; i < charCodes.length; i++) {
const charCode = charCodes[i]
if (!charCode) {
continue
}
result += String.fromCharCode(charCode)
}
result // 'shit'
const charCodes = [98, 101, 116, 116, 101, null, 114]
const result = charCodes
.filter((charCode) => charCode)
.map((charCode) => String.fromCharCode(charCode))
.join('')
result // 'better'
const charCodes = [110, 105, null, 99, 101]
const makeWord = pipe(
reject(isNil),
map(String.fromCharCode),
join('')
)
makeWord(charCodes) // 'nice'
const incCount = ifElse(
has('count'),
over(lensProp('count'), inc),
assoc('count', 1)
)
incCount({}) // { count: 1 }
incCount({ count: 1 }) // { count: 2 }
const toUnicorn = (horse) => {
const whiteHorse = paint(🥛, horse)
const hornedWhiteHorse = attach(🐚, whiteHorse)
return feed(🌈, ✨, hornedWhiteHorse)
}
toUnicorn(🐴) // 🦄
const toUnicorn = pipe(paint(🥛), attach(🐚), feed(🌈, ✨))
toUnicorn(🐴) // 🦄
pipe = (…fns) → (a) → b
import { pipe } from 'ramda' // or: 'lodash/fp'
const toUnicorn = (horse) => pipe(
(horse) => paint(🥛, horse),
(whiteHorse) => attach(🐚, whiteHorse),
(hornedWhiteHorse) => feed(🌈, ✨, hornedWhiteHorse)
)(horse)
toUnicorn(🐴) // 🦄
const curriedPaint = (color) => (thing) => paint(color, thing)
const curriedAttach = (item) => (thing) => attach(item, thing)
const curriedFeed = (food1) => (food2) => (thing)
=> feed(food1, food2, thing)
const toUnicorn = (horse) => pipe(
curriedPaint(🥛),
curriedAttach(🐚),
curriedFeed(🌈)(✨)
)(horse)
toUnicorn(🐴) // 🦄
const curriedPaint = (color) => (thing) => paint(color, thing)
const curriedAttach = (item) => (thing) => attach(item, thing)
const curriedFeed = (food1) => (food2) => (thing)
=> feed(food1, food2, thing)
const toUnicorn = (horse) => pipe(
curriedPaint(🥛),
curriedAttach(🐚),
curriedFeed(🌈)(✨)
)(horse)
toUnicorn(🐴) // 🦄
const curriedPaint = (color) => (thing) => paint(color, thing)
const curriedAttach = (item) => (thing) => attach(item, thing)
const curriedFeed = (food1) => (food2) => (thing)
=> feed(food1, food2, thing)
const toUnicorn = pipe(
curriedPaint(🥛),
curriedAttach(🐚),
curriedFeed(🌈)(✨)
)
toUnicorn(🐴) // 🦄
import { curry } from 'ramda' // or: 'lodash/fp'
const curriedPaint = curry(paint)
const curriedAttach = curry(attach)
const curriedFeed = curry(feed)
const toUnicorn = pipe(
curriedPaint(🥛),
curriedAttach(🐚),
curriedFeed(🌈, ✨)
)
toUnicorn(🐴) // 🦄
import { curry } from 'ramda' // or: 'lodash/fp'
const paint = curry((color, thing) => /* paint thing */)
const attach = curry((item, thing) => /* attach thing */)
const feed = curry((food1, food2, thing) => /* feed thing */)
const toUnicorn = pipe(
paint(🥛),
attach(🐚),
feed(🌈, ✨)
)
toUnicorn(🐴) // 🦄
const toUnicorn = (horse) => {
const whiteHorse = paint(🥛, horse)
const hornedWhiteHorse = attach(🐚, whiteHorse)
return feed(🌈, ✨, hornedWhiteHorse)
}
toUnicorn(🐴) // 🦄
End result:
const toUnicorn = pipe(paint(🥛), attach(🐚), feed(🌈, ✨))
toUnicorn(🐴) // 🦄


| Name | Materials | Address | POC Name | POC Details |
|---|---|---|---|---|
| Bay Area Recycle | Concrete, Dirt | 24701 clawiter, Hayward, CA | tom |<PHONE_NUMBER> |
| Vienna corporetions | Asphault, Recycle, Dirt, Sand, Concrete | 12800-12836 Concepcion Rd, Los Altos Hills, CA | Tedd |<PHONE_NUMBER> |
| Ashton Private Ltd. | Asphault, Recycle | 14000 Fruitvale Ave, Saratoga, CA | Tyson |<PHONE_NUMBER> |
| Material Solutions | Concrete, Dirt, Sand | 1235 Wildwood Ave, Sunnyvale, CA | Cadelene |<PHONE_NUMBER> |
| Airi Corporation | Asphault, Recycle | Santa Clara, California | Roshin |<PHONE_NUMBER> |
| Brielle Williamson Limited | Dirt, Sand | 725 Sylvan Ave, Mountain View, CA | Hrithik |<PHONE_NUMBER> |
| California Recycles | Recycle, Asphault, Sand | 1656 McCarthy Blvd, Milpitas, CA | Valdimer |<PHONE_NUMBER> |
| American Recycle Corporations | Concrete, Recycle, Asphault | 2169-2173 Benton St, Santa Clara, CA | Ferry |<PHONE_NUMBER> |
| CAQ Solutions | Asphault, Recycle, Sand | 830 Auzerais Ave, San Jose, CA | Derrick |<PHONE_NUMBER> |
| Recyclable CA | Recycle, Asphault, Dirt, Sand, Concrete | Cupertino, California | Reck |<PHONE_NUMBER> |


Electric vehicle charging station opens off I-15 in Nevada
LAS VEGAS (AP) - Electric vehicle owners have a new place to charge batteries on the heavily-traveled freeway between Las Vegas and Los Angeles.
State and local officials on Thursday marked the start of use of two rapid chargers at a Terrible’s Road House service station in Jean.
That’s off Interstate 15, about 30 miles (48.3 kilometers) south of Las Vegas.
TOP STORIES
Franklin Graham calls on nation to pray for Trump as impeachment effort gains speed
George Soros group asks Fox News to ban guest who claimed billionaire controls State Dept.
Nancy Pelosi goes for slam dunk -- and crashes to court
It’s the first of its kind on I-15 in Nevada and the fifth site in the state under a program launched in 2016 by the Governor’s Office of Energy, Nevada utilities and local businesses.
The aim is to put charging stations at strategic locations around the state.
Other charging stations are on U.S. 95 in Fallon, Hawthorne, Tonopah and Beatty (BAE’-tee).
Officials say one is scheduled to open in Indian Springs in February.
Sign up for Daily Newsletters
Copyright © 2019 The Washington Times, LLC.
Please read our comment policy before commenting.


Rhubarb Upside-down Cake
From: Saveur • Print this Recipe
Search Results
To be perfectly honest, this is more of a large rhubarb-topped scone than an upside down cake, but I’m perfectly OK with that. Best eaten warm, with fresh whipped cream!
Ingredients:
- ¾lb. rhubarb (4-5 medium-large stalks), trimmed and cut into 1½” pieces on an angle
- 1½ cups sugar
- 4 tbsp. unsalted butter, plus 6 tbsp. cut into ½” cubes and chilled
- 1 tbsp. fresh lemon juice
- 2 tsp. vanilla extract
- ½ tsp. kosher salt
- 2½ cups flour
- 2 tsp. baking powder
- ½ cup vegetablespoon shortening
- ⅓ cup milk
- 2 eggs
Directions:
- Heat oven to 375°F.
- Combine rhubarb, 1 cup sugar, 4 tbsp butter, lemon juice, vanilla, and 1⁄4 tsp salt in a 9” skillet over medium heat. Cast iron works best, as you can put it directly in the oven, but I used a regular nonstick pan then transferred into a cake pan for baking and it came out just fine.
- Cook, stirring occasionally, until sugar is melted and rhubarb is tender and slightly caramelized, 8-10 minutes.
- Meanwhile, whisk together remaining sugar and salt, plus flour and baking powder in a bowl.
- Add remaining butter and the shortening and, using your fingers or a pastry cutter, rub into flour mixture to form coarse pea-size pieces.
- Add milk and eggs and stir until a soft, sticky dough forms (I ended up needing to add just a teaspoon more milk, but use your best judgement).
6.5 If using a nonstick skillet, transfer the rhubarb mixture into an ungreased cake pan.
- Place spoonfuls of dough over rhubarb mixture and smooth with a nonstick spatula. Imperfections are OK! Luckily, this will be the bottom of your cake.
- Bake until the crust is golden and cooked through, about 30 minutes.
- Remove skillet from oven; place a large flat serving platter on top of the skillet and invert quickly and carefully.
Serve warm or at room temperature with ice cream or whipped cream, if you like.


Tip Top bakery workers fighting to put bread on their table
by First UnionTip Top bakery workers fighting to put bread on their own tables
Source: First Union
--
WHAT:
More than 100 FIRST Union members at George Weston Foods’ Tip Top bakeries in Auckland (Otahuhu, Wiri) are striking over the company’s ongoing refusal to offer a fair pay rise and a premium on overtime and night work. The union has been in bargaining with the company since July and despite prolonged negotiations, only a minimal pay increase has been offered.
The deal proposed by Tip Top would see the minimum wage overtake the bottom rate in the agreement. Many of the workers put in upwards of 50-60 hours a week, including long night shifts, to keep up the company’s 24/7 operation. They receive no overtime rate, no night rate and no special recognition for the family time they sacrifice on a weekly basis.
As part of ongoing strike action, workers are picketing outside Tip Top’s Otahuhu bakery.
WHERE:
Outside the Tip Top bread factory, 638 Great South Road, Papatoetoe, Auckland.
WHEN:
Monday 25th November 2019, 08:30am onwards
WHY:
"Tip Top bakery workers are fighting to put bread on their own tables after years of negligible pay rises and no recognition of the family time they have to sacrifice to enable the company’s 24/7 operation," said Anita Rosentreter, FIRST Union spokesperson.
"Tip Top bakery workers are sick of making bread rise without a decent pay rise."
"Tip Top is owned by global corporation George Weston Foods, which makes billions of dollars of profit. Meanwhile, many of their workers can barely cover their bills."
"George Weston Foods is using their employees’ low pay against them: they know our members have to work 50 or more hours a week to make ends meet. If they paid them more, they would be able to spend less time at work and more time at home with their families."
ENDS


POJOSS, Acquinas, St. Johns students in court for impersonation
Eight students from St. Johns Grammar, St.Thomas Aquinas, and Pope John Senior High Schools are before a Koforidua District Magistrate Court for impersonating during West Africa Senior Secondary Certificate Examination(WASSCE) for private candidates held in September this year.
According to the Complainant, John M.K Jentuh, a teacher and Examination Supervisor at Pope John SHS Examination Center, the students were fished out during biometric verification of candidates in separate days.
Four of the accused persons, including a 24-year-old from Akrade in Asuogyaman district, have been convicted on their own plea , fined Ghc1,200 each and signed a year bond of good behaviour.
They were convicted by the Presiding Judge, His Worship Nana Osei Assibey after social enquiry report by the Department of Social welfare.
Two of the suspect students- both 17 years from St.Thomas Aquinas and St.John Grammar – who allegedly conspired and impersonated during the examination have jumped bail hence a bench warrant has been issued for their arrest on Friday, November 22, 2019.