Implementing StarGAN
Paper: StarGAN: Unified Generative Adversarial Networks for Multi-Domain Image-to-Image Translation
Introduction
Image-to-image translation refers to mapping images between different domains. For example, changing the facial expression of a person from smiling to frowning, or changing the gender of a person from male to female, or their hair color from black to brown.
For each domain (ex: black_hair_color
, or beard
) every image has a value. In the dataset that we use, the values are yes/no. Of course, it's possible that these domains or aspects of images don't vary independently in naturally occuring examples. But that's what makes some of the results interesting 😄.
StarGAN1 performs this image-to-image translation task for face images. Before StarGAN, to learn mappings between 4 domains, we'd need 12 networks. Why? Let A, B, C and D be the domains. Then we have
\[ \begin{aligned} I_A &\xrightarrow{G_1} I_B \\ I_A &\xrightarrow{G_2} I_C \\ I_A &\xrightarrow{G_3} I_D \\ &\ldots \\ I_D &\xrightarrow{G_{10}} I_A \\ I_D &\xrightarrow{G_{11}} I_B \\ I_D &\xrightarrow{G_{12}} I_C \end{aligned} \]
where \(I_A\in A, I_B \in B \ldots\) are images in their respective domains. As you can see we'd need \(G_1 \ldots G_{12}\) to perform the translations.
StarGAN learns to map between multiple domains by using a single network. Roughly, it achieves this by passing in domain information to the network: \[ \begin{aligned} I_A,F_B &\xrightarrow{G} I_B \\ I_C,F_D &\xrightarrow{G} I_D \\ \end{aligned} \] where \(F_B\) and \(F_D\) encode information of output domain.
 Each attribute is \(\{0,1\}\) such as Brown_Hair
, Young
, Big_Nose
, etc.
The preprocessing pipeline for the images is:
The green blocks are augmentation blocks, and red blocks are transformation blocks.
Principal
The idea is to have a generator take in a source image \(I\), and a \(\{0,1\}\) attribute vector \(\vec{l}\) which describes the target domain. The generator output \(I_o\) is then fed into a classifier that checks if \(I_o\) can be classified as \(\vec{l}\). An additional objective ensures that the difference between \(I\) and \(I_o\) is minimized so that the images look similar (imagine same person with different hair color for example).
Before we delve into StarGANs details, a brief introduction to GAN (Generative Adversarial Networks) is given below.
Overview of GANs
Generative Models
Generative adversarial networks are an example of generative models 2
A generative model takes a dataset consisting of samples drawn from a training set \(p_{data}\) and learns to represent and estimate of that distribution somehow. The result is the probability distribution \(p_{model}\).
Among the many reasons for studying generative models, one that I find most motivating is the ability of generative models to work with multi-modal outputs i.e. there are many correct answers to a possible question (Ex: "generate image of a dolphin" can generate a lot of different variants). However, if we use MSE, for instance, the output will be the average of all correct answers which is not always desired.
From the maximum likelihood lens, the objective of a generative model is to find parameters \(\theta\) that maximize the likelihood of the training data \(x^{(i)}\) where \(i \in \{1, \ldots, m\}\) which means there are \(m\) examples in the training set. \[ \theta^* = \arg\max_\theta{\sum_{i=1}^m\log p_{model}(x^{(i)};\theta)} \] Equivalently \[ \theta^* = \arg\max_\theta{\mathbb{E}_{x\sim p_{data}}\log p_{model}(x;\theta)} \]
In explicit models, you explicitly write down the likelihood of the data under \(p_{model}\). However, maximizing it is another challenge since gradient-based methods may not be computationally tractable in all cases.
In implicit models, you can only sample from the estimated density, not express the density itself i.e. you can only interact with \(p_{model}\) by sampling from it. GANs are an example of implicit models.
Summary of GAN
The generator \(G\) in a GAN transforms a random variable \(Z\) to \(X\) which is in the space we care about. Therefore, \(G\) gives us a way to sample from \(p_{model}\). But how do we tune the parameters \(\theta\) of distribution \(G(Z)\) so that we can increase the likelihood? Well, we can do it by evidence.
One way is to judge if the samples from \(p_{model}\) are indistinguishable from samples from \(p_{data}\).The hypothesis is that if this is done for enough samples, then we can make an accurate judgement about \(p_{model}\) i.e. be able to tell if \(p_{model}\) is close to \(p_{data}\) or not.
To make this judgement, we use a discriminator \(D\). The discriminator is taught to recognize whether a sample is from \(p_{data}\) or not. If the discriminator can recognize this perfectly, then in theory \(G\) can tune it's parameters \(\theta\) until \(D\) evaluates all outputs of \(G\) (i.e. \(p_{model}\)) to be sampled from \(p_{data}\) as well.
GAN Loss Function
For a GAN discriminator \(D\), we use the standard cross-entropy cost: \[ J^{(D)}(\theta,\phi) = -\frac{1}{2}\mathbb{E}_{x\sim p_{data}}\log(D(x)) -\frac{1}{2} \mathbb{E}_{z}\log(1-D(G(z))) \] There are multiple choice of losses for the generator \(G\). One is \(J^{(G)}=-J^{(D)}\) i.e. try to maximize discriminator loss which would mean that discriminator will classify generator outputs.
From the standpoint of ensuring that both discriminator and generator have strong gradients when they're "wrong", we change the functions up a bit; however, these are heuristics.
Note: As a standard, for \(D\) label \(0\) means fake, and label \(1\) means real. So for all generated inputs, it must predict \(0\).
StarGAN Overview
Output
Generator
The basic generator architecture is as follows:
Discriminator
The discriminator architecture:
According to the paper, the discriminator leverages PatchGANs
which classify whether local image patches are real or fake.
However, in the network described in the appendix, the output \(D_{src}\) is not 1-dimensional. Instead it's 2x2
for a 128x128
image. This is because the size of output is \(\left(\frac{h}{64},\frac{w}{64},1\right)\).
In the PatchGAN architecture, in the last layer a convolution is applied to get a 1D output, followed by a Sigmoid function. Accordingly, we make the following modifications to the StarGAN architecture:
- Final Conv
kernel_size=2, padding=0
to get 1D output - Sigmoid applied to get output \(\in [0,1]\)
The other output of the discriminator is used to compute classification loss, which is described later.
Training Methodology
There are three losses in StarGAN and the Generator and Discriminator have different goals with regards to these functions
Adversarial Loss
\[ L_{adv} = \underbrace{\mathbb{E}_x[\log D_{src}(x)]}_{\alpha} + \underbrace{\mathbb{E}_{x,c}[1-\log D_{src}(G(x,c))]}_{\beta} \] It helps to think here that \(D_{src}(x) = P(\text{real}|x)\) i.e. probability that the source of \(x\) is real or fake.
\(D\) wants to maximize it's ability to tell real and fake apart. So it wants that \(P(\text{real}|x_{real}) \uparrow\) and \(\left(P(\text{fake}|x_{fake}) = 1-P(\text{real}|x_{fake})\right)\uparrow\) i.e. \(P(real|x_{fake})\downarrow\)3
Which means, \(D\) wants to maximize \(L_{adv}\). On the other hand, \(G\) wants to make sure that \(D\) classifies generated images as real, therefore \(G\) wants to maximize \(P(real|x_{fake})\) i.e. minimize \(\beta\) term which is effectively trying to minimize \(L_{adv}\) since \(G\) is only present in \(\beta\).
In reality, StarGAN uses the Wasserstein GAN objective to stabilize training (more on WGAN loss in later posts 🔮) \[ L_{adv}(D) = \underbrace{\mathbb{E}_x[D_{src}(x)]}_{\alpha} - \underbrace{\mathbb{E}_{x,c}[D_{src}(G(x,c))]}_{\beta} -\underbrace{\lambda_{gp}\mathbb{E}_{\hat{x}}\left[(\|\nabla_{\hat{x}}D_{src}(\hat{x})\|_2-1)^2\right]}_{\gamma} \] where the \(D\) wants \(\alpha\uparrow\), \(\beta \downarrow\), and \(\gamma \downarrow\). If we take signs into account, then we find that \(D\) wants to minimize \(-L_{adv}(D)\). Also, here \(\hat{x}\) is sampled from a straight line between fake and real images.
The adversarial loss for \(G\) on the other hand is \[ L_{adv}(G) = \underbrace{\mathbb{E}_{x,c}[D_{src}(G(x,c))]}_{\beta} \] where \(G\) wants \(\beta \uparrow \implies -L_{adv}(G)\downarrow\)
Classification Loss
Because we're using a single \(G\) network to generate images for all domains, we pass in target domain information say \(F_A\) for domain \(A\) to \(G\) as well. For the generated image \(I\), we want the discriminator to both think it's real and classify it as \(I\in A\).
Therefore, we have a classification loss as well. Since the labels in this task look like:
The classification for each image is multilabel multiclass. Therefore the loss is a sigmoid followed up binary cross entropy on each class \(c^i_I\) for class vector \(\vec{c}_I\) of image \(I\):
\[ L_{cls}(D) = \sum_{i} \text{BCELoss}(D(I)^i, c^i_I) \] For generator \[ L_{cls}(G) = \sum_i BCELoss(D(G(I,c))^i, c^i) \] where \(c\) is a class vector used to domain transfer image \(I\) to labels \(c\). In summary , \(G\) wants to generate images that fool the discriminator, and that are classified in the correct class.
Reconstruction Loss
Lastly, we want to ensure that the only difference between \(x\) and resulting \(y\) is that of the domain. To handle this, we apply a cycle consistency loss i.e. transform image to class \(c\), then transform output to class \(c'\) which is class of \(x\). \[ L_{rec} = \mathbb{E}_{x,c,c'}[\|x - G(G(x,c),c')\|_1] \] Note about Generator Training: When generator is being trained, random labels are fed in for images, instead of true labels. This means the generator may be asked to perform multiple domain translations at once. As to whether its better performance when a single domain translation is required, vs. multiple domain translations, that's hard to tell. But it is assumed that the generator will eventually learn which entry in the domain vector correspond to what domain (i.e. for example \(d[3] = 1\) => Black Hair)
Important things during training
- Pytorch optimizers minimize the loss since they subtract the gradient from the loss function \(\implies\) pytorch performs gradient descent. Therefore, all objectives must be specified as min objectives.
- GAN training requires alternating between training the discriminator, and the generator. In StarGAN, there's 1 iteration of training \(G\) for every 5 iterations of training \(D\).
Results
We compare the results on the same sample of images earlier in the training vs. after 90K iterations. For each image, the samples are generated by flipping the value of 1 attribute.
In the training (and sampling), the selected attributes are:
[Black_Hair, Blond_Hair, Brown_Hair, Male, Young]
Caveat: Attributes associated with hair color are not flipped. Instead one of them is set to 1
while other hair color attributes are set to 0
.
[Black_Hair, Blond_Hair, Brown_Hair, Male, Young]
Observe the changing hair colors, and changed face structure to reflect gender/age.
What's wrong with StarGAN?
We randomly generate the target domain label so that \(G\) learns to flexibly translate the input image.
This makes no sense. Assume there are 5 domains. Then the domain labels for that image are of the type \([d_1, d_2, d_3, d_4, d_5]\) where \(d_i \in \{0,1\}\). If you feed in random labels for an image, then how does provide any hint to the generator? And if the purpose later on is to control for all domains except the one that is changed, then how will the generator learn for test time? Shouldn't test conditions be the same as train conditions? Because during sampling/testing the label vector for the source image is preserved except the attribute that needs to be changed for ex: changing hair color.
FAQ
Generator Input
Class vector \(\vec{c} \in \{0,1\}^n\) where \(n\) is the number of classes. Then how is the label vector appended to the image to feed into the generator?
Consider image of size \(4\times4\) and \(n=2\) so the labels are changed like so:
array([1, 1])
array([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]],
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]])
After appending to a 3-channel image \(3\times4\times4\) the final size is \(5\times4\times4\). This is the input to the generator.
Logits
From the SO answer: https://stackoverflow.com/questions/41455101/what-is-the-meaning-of-the-word-logits-in-tensorflow
The raw predictions which come out of the last layer of the neural network.
The logit seems to refer to real-valued tensor that is fed into some activation function to get the task output or before applying loss function to it. In case of classification, logit transforms real-valued tensor to probabilities.
This comes from the math definition of logit which refers to functions mapping probabilities \([0,1]\) to \([-\infty, +\infty]\). In context of NN, instead of the function(s), logit refers to the output of the function (which is to be fed into an activation function to get probabilities).
GPU Computation
As long as you make sure that all your leaf-nodes in the computation graphs are placed on the GPU, all operations will happen in the GPU.
Therefore, for every input tensor, place it on GPU by using .to(device)
Pytorch detach()
pytorch detach operation on tensors:
The only thing detach does is to return a new Tensor (it does not change the current one) that does not share the history of the original Tensor.
Why is x_fake.detach()
is perfomed before passing the tensor to the discriminator? This is because we want to treat it as an ordinary input to the discriminator, and while training do not want to propagate the gradients back to the generator. While training the generator, we'll push the gradients (at that time we should zero out the gradients of the discriminator).
Gradient Penalty
def gradient_penalty(y, x):
"""Compute gradient penalty: (L2_norm(dy/dx) - 1)**2."""
weight = torch.ones(y.size()).to(self.device)
dydx = torch.autograd.grad(outputs=y,
inputs=x,
grad_outputs=weight,
retain_graph=True,
create_graph=True,
only_inputs=True)[0]
dydx = dydx.view(dydx.size(0), -1)
dydx_l2norm = torch.sqrt(torch.sum(dydx**2, dim=1))
return torch.mean((dydx_l2norm-1)**2)
Why is gradient penalty computed this way?
only_inputs=True
because the input x
is a mixture of generated fake images, and real images. When computing the gradient, we don't want the gradient to propagate through the generator.
create_graph=True
because y
is discriminator output of x
, and gradient penalty term is present in adversarial loss \(L_{adv}\) for the discriminator. We want this term to be differentiable w.r.t. parameters of D
i.e. we'll be computing: \[
\partial\left(\frac{\partial (\hat{x})}{\hat{x}}\right)/\partial \theta
\] create_graph
indicates that we need the graph for the backward step. We don't have retain_graph=True
because we don't need this graph after backward
is called once. For different inputs, the graph is reconstructed (i.e. for each iteration of training there is a new graph).
References
The modified code can be found in the repository https://github.com/altairmn/stargan.


labeled
by Max Kadel at 2023-01-30 13:23:55.head_ref_force_pushed
by Max Kadel at 2023-01-30 15:53:23.head_ref_force_pushed
by Max Kadel at 2023-01-30 15:57:19.deployed
by None at 2023-01-30 16:21:48.referenced
by Kevin Reiss at 2023-01-30 16:30:35.merged
by Kevin Reiss at 2023-01-30 16:30:36.closed
by Kevin Reiss at 2023-01-30 16:30:36.head_ref_deleted
by Kevin Reiss at 2023-01-30 16:30:37.labeled
by Kevin Reiss at 2023-01-30 16:54:30.labeled
by Kevin Reiss at 2023-01-30 16:54:30.FYI, here is the procedure I followed for the non-search parameters deprecation: https://github.com/pulibrary/orangelight/issues/3338#issue-1517815840
referenced
by Jane Sandberg at 2023-01-30 18:08:00.merged
by Jane Sandberg at 2023-01-30 18:08:00.closed
by Jane Sandberg at 2023-01-30 18:08:01.head_ref_deleted
by Jane Sandberg at 2023-01-30 18:08:02.labeled
by Max Kadel at 2023-01-30 20:52:40.referenced
by Max Kadel at 2023-01-30 21:09:13.Initial analysis: https://www.oclc.org/content/dam/oclc/fast/FAST-quick-start-guide-2022.pdf is a guide to FaST.
It lists 9 sections of FAST: Topical Personal Names Corporate Names Meetings Named Events Uniform Titles Chronological Geographic Form/Genre
Of those, Named Events is the only area without a direct equivalent in LCSH.
The rest are simply derived from the LCSH equivalents, with some key differences. 1. Place names are always hierarchical and always in their 'natural order'. a. LCSH: Fuji, Mount (Japan) b. FaST: Japan -- Mount Fuji 2. Name-title headings are formed in FaST by starting with the title, then placing the name after. a. LCSH: Vonnegut, Kurt. Slaughterhouse-five b. FaST: Slaughterhouse-five (Vonnegut, Kurt) 3. In general, FaST consists of the individual facets of assigned LCSH split into the 9 segments listed above. a. LCSH: 650 _0 $a Internal migrants $z China $z Beijing $v Fiction. b. FaST: 1. 650 _7 $a Internal migrants. 2. 651 _7 $a China $z Beijing. 3. 655 _7 $a Fiction.
There are other differences, but those are the most significant.
I am running some scripts to gather data on how FaST is currently used at PUL. 1. Find records that do not have LCSH/LCGFT but have FaST headings. 2. Of records that have LCSH/LCGFT and FaST, which records have headings unique to the FaST vocabulary that aren't directly represented by LCSH/LCGFT? This will also show all FaST headings on records with both vocabularies.
My hope is that these analyses will be used to inform us how to implement this request and its priority.
See this report for records with FaST headings but no LC headings: https://docs.google.com/spreadsheets/d/1N_Orxap8UTb4eJt8NDZKhnQA4wQp95ShI4fphkOf8ao/edit?usp=sharing
There are 2,635 such records out of 11,802,517 unsuppressed records in Alma. Records have not been further assessed (belonging to the Community Zone, records that are not yet fully cataloged, etc.).
See this report for records with LC headings that also have unique FaST headings: https://docs.google.com/spreadsheets/d/1Yt-fARTeLg_V2ok-kVhUAWUijAbnLuHEuvPQgjGhhT4/edit?usp=sharing
There are 353,931 such records out of 11,802,517 records in Alma.
Many of them have near-equivalent matches in LC, e.g., World War, 1939-1945
vs. World War (1939-1945)
.
Many others only have chronological headings, e.g., 1900 - 1999
, which were derived from other areas of the record.
See this report for records with LC headings that have FaST headings completely duplicated by LC portions: https://docs.google.com/spreadsheets/d/1o4wkiChs1mFGI7E_yE80sMchxGiQirYLBdONCyEsNmU/edit?usp=sharing
There are 422,873 such records out of 11,802,517 records in Alma.
Overall summary: 1. Roughly 7% of our records have FaST headings. 2. Roughly 54% of those records have FaST headings with information that is entirely duplicated by LC headings. 3. Roughly 0.02% of our records only have FaST headings.
I switched to fuse, which worked well, but we decided to hold off implementing search for now.
closed
by Cliff Wulfman at 2023-01-30 15:31:43.assigned
by Taylor Yamashita at 2023-01-30 19:18:27.labeled
by None at 2023-01-30 23:05:12.Superseded by #146.
closed
by None at 2023-01-30 23:05:14.head_ref_deleted
by None at 2023-01-30 23:05:16.Putting this ticket on hold for now. I have changed decorators to wayfinders in all the places I've found at the moment.
assigned
by Robert-Anthony Lee-Faison at 2023-01-30 15:27:10.@tpendragon added
mentioned
by Trey Pendragon at 2023-01-30 20:11:42.subscribed
by Trey Pendragon at 2023-01-30 20:11:42.referenced
by Eliot Jordan at 2023-01-30 20:30:38.merged
by Eliot Jordan at 2023-01-30 20:30:38.closed
by Eliot Jordan at 2023-01-30 20:30:38.head_ref_deleted
by Eliot Jordan at 2023-01-30 20:30:39.Coveralls shows its last run as being from March 2019 before we changed the main branch name. Coverage at that time was 95%.
coverage on a current run of simplecov is 81.66%. This appears to be due to some new contacts functionality that isn't tested, and record mailer, which seems to have been around for a while but I don't see in the coveralls report.
closed
by Eliot Jordan at 2023-01-30 20:30:40.head_ref_force_pushed
by None at 2023-01-30 20:31:47.Deprecation warnings on BL 7.33.0:
render Blacklight::SearchBarComponent.new
instead). (called from appviewssharedheadernavbarhtmlerb__90396678686799367257000 at /Users/eliotj/Documents/Repositories/lae-blacklight/app/views/shared/headernavbar.html.erb:27) NOTE: This new
takes arguments, deprecation warning does not advise, we used https://github.com/projectblacklight/blacklight/blob/main/app/views/catalog/_search_form.html.erb as a reference.reference commits on orangelight: https://github.com/pulibrary/orangelight/search?o=desc&q=%22deprecation+warning%22&s=committer-date&type=commits
labeled
by Kevin Reiss at 2023-01-30 17:05:09.@mzelesky and I reviewed the search results of this PR. It seems to be a little bit more complicated and we should discuss this in the Orangelight meeting on 2/9/2023.
mentioned
by None at 2023-01-30 15:30:43.subscribed
by None at 2023-01-30 15:30:43.labeled
by Christina Chortaria at 2023-01-30 16:05:22.renamed
by Christina Chortaria at 2023-01-30 18:18:53.labeled
by Jane Sandberg at 2023-01-30 22:17:28.assigned
by Jane Sandberg at 2023-01-30 22:17:28.closed
by Hector Correa at 2023-01-30 14:27:00.referenced
by Hector Correa at 2023-01-30 14:26:57.merged
by Hector Correa at 2023-01-30 14:26:57.closed
by Hector Correa at 2023-01-30 14:26:57.head_ref_deleted
by Hector Correa at 2023-01-30 14:26:59.assigned
by Tyler Wade at 2023-01-30 14:38:07.labeled
by Bess Sadler at 2023-01-30 14:56:38.I hope we are not really minting new ARKs every time we run the tests.
labeled
by Tyler Wade at 2023-01-30 17:05:44.ready_for_review
by Chuck McCallum at 2023-01-30 20:42:49.convert_to_draft
by Chuck McCallum at 2023-01-30 22:00:06.head_ref_force_pushed
by None at 2023-01-30 16:37:19.deployed
by None at 2023-01-30 16:38:23.deployed
by None at 2023-01-30 16:54:34.ready_for_review
by None at 2023-01-30 16:58:24.deployed
by None at 2023-01-30 18:25:39.deployed
by None at 2023-01-30 18:50:47.deployed
by None at 2023-01-30 19:53:28.Related to #3423
See also https://bundler.io/doc/troubleshooting.html#other-problems for tips on getting rid of wrong versions of bundler.
head_ref_force_pushed
by Francis Kayiwa at 2023-01-30 21:06:45.head_ref_force_pushed
by Francis Kayiwa at 2023-01-30 21:22:51.referenced
by Francis Kayiwa at 2023-01-30 21:54:18.merged
by Francis Kayiwa at 2023-01-30 21:54:18.closed
by Francis Kayiwa at 2023-01-30 21:54:19.head_ref_deleted
by Francis Kayiwa at 2023-01-30 21:54:20.head_ref_force_pushed
by None at 2023-01-30 16:06:40.head_ref_force_pushed
by None at 2023-01-30 17:52:47.head_ref_force_pushed
by None at 2023-01-30 18:58:11.head_ref_force_pushed
by None at 2023-01-31 02:35:34.closed
by Trey Pendragon at 2023-01-30 19:43:27.referenced
by Trey Pendragon at 2023-01-30 19:17:18.merged
by Trey Pendragon at 2023-01-30 19:17:18.closed
by Trey Pendragon at 2023-01-30 19:17:18.head_ref_deleted
by Trey Pendragon at 2023-01-30 19:18:14.


Data Fields | |
| int | num_opers |
| L_Oper ** | oper |
| int | type |
| int | initial_height |
| float | prob |
| int * | heights |
Definition at line 1076 of file l_schedule.c.
| int* LEAF::heights |
Definition at line 1083 of file l_schedule.c.
Definition at line 1081 of file l_schedule.c.
| int LEAF::num_opers |
Definition at line 1078 of file l_schedule.c.
| L_Oper** LEAF::oper |
Definition at line 1079 of file l_schedule.c.
| float LEAF::prob |
Definition at line 1082 of file l_schedule.c.
| int LEAF::type |
Definition at line 1080 of file l_schedule.c.


BwackNinja's Hideout
home
|
projects
|
about
{% for post in site.posts %}
{{ post.title }}
{% endfor %}


This is the homepage for your Gradebook. Look below for links to all the resources you need.
View all your current assignments and the grades awarded to each assignment.
Missed a class due to illness or any other situation beyond your control? No worries, Get all the notes right here! They are posted for you by your teacher.
© Copyright 2017 Tommy Gooden - All rights reserved.


Preprocessing
ELAC’s components PMM and ML expect the presence of corpora in MMAX2 format which have already been processed by JavaRap and BART (LingPipe will be executed on the fly). The directory containing the MMAX2 files should therefore also contain the results of those two systems. This is done to save runtime as on-the-fly execution of BART and JavaRap tends to be too time consuming.
To achieve a better overall performance, we implemented a preprocessing package, which does the following:
- Run JavaRap on a MMAX2 corpus and store the results under
./Basedata/javarap/
- Convert a Salsa/Tiger Corpus into an interims format using inline annotation
JavaRapPreprocessing
This class provides the conversion features needed to process both training and test data with JavaRap and stores their results so that they can be used by JavaRapRunner afterwards.
As JavaRap (especially the underlying reranking parser) tends to be difficult to compile, it’s possible to execute JavaRap remotely on a specified server (username and password required to establish a secure connection).
Javarap.jar
is required: http://aye.comp.nus.edu.sg/~qiu/NLPTools/JavaRAP.html
How to use:
JavaRapPreproecessing is accessible through ELAC’s command line interface.
You are prompted for the following options
ssh/local
: specify remote or local execution.JavaRapPath
: Path to the JavaRap installation (AnaphoraResoultion.jar
has to exist).
To run JavaRap Preprocessing:
- make sure that training and test files have been specified correctly in the config file
- To run JavaRap using a remote connection: choose the appropriate in the Command Line Interface (option 1 – execution via ssh) – Note: you are prompted for the hostname, a temporary directory on the server, where rights are set correctly (at least +w) and your credentials.
- To run JavaRap locally: choose the appropriate in the Command Line Interface (option 2 – local execution) and specify
JavaRapPath
The alignment from JavaRap to MMAX2 is done by word positions, which are not stored in MMAX2 but used by JavaRap to display the coreferences. This is done by iterating over all the words produced by JavaRap output and mapping the positions to the appropriate Word
objects which have been extracted by MMAxParser
.
The results are stored in the folder ./Basedata/javarap/
for the corresponding MMAX2 corpus.
TigerPreprocessing
The Tiger/Salsa Format consists of a standoff annotation, where coreference links are attached to words and phrases by graph structures.
This format is converted into an interim format using inline annotation, where coreferences are marked by XML-Tags. A chain of coreferent expressions is marked by the same coref_set
attribute value.
This XML file can then be converted into an MMAX2 project using the MMAX2 Annotation Tool’s Project wizzard.
How to use
TigerPreprocessing is accessible through ELAC’s command line interface (Menu option Salsa Parser
).
You are prompted for the following options:
input file
The file to be processed in a valid Tiger/Salsa xml format.output file
Destination for the inline annotated output file.
0 Comments.


{% extends "notesapp/onboarding/onboarding-base.html" %} {% from "notesapp/_macros.html" import render_tag_input, render_new_tag_input, render_pagination %} {% block msg_box_content %}
You can create labels for your objectives:
You can keep adding labels whenever you need to.


Updated: 2015-08-30 to support the 0.6.0 API.
For some reason, the first thing I look for when I’m building an application is
authentication. For me things are interesting when there’s something going on on
my apps, and that usually means letting people login.
I’ve been enjoying Elixir and so far there hasn’t been anything for
authentication that suited what I wanted. Using Phoenix is so nice, and make
things that are difficult or nearly impossible with other frameworks easy
(looking at you Channels).
One of the things that I really like about Elixir/Eralng, is that making all
elements of you application live in your application is (mostly) reasonable. Web
requests, web-sockets, mail even raw TCP sockets are all on the table. Time for
something new in auth.
Guardian is based on JWT. They are the self contained package of information that contains all the information you need for your authentication needs. For those unfamiliar I suggest having a look at the Registered Claim Names. These little packets of goodness can be used in a session, authorization header, passed in body params - they can even be used on raw sockets.
Lets look at what Guardian is not (for the moment).
- It does not have any requirements around your model
- It does not try to implement (or assist you to implement) checking login/emails
- It does not try to do oAuth
Not to say that strategies won’t come sometime in the future, but for the moment
I’m not convinced that they’re actually within scope of the library. Guardian
strives to provide mechanisms for seamless authentication across different
access patterns, devices and S2S communications. How you determine that a user
is who they say they are is, at the moment beyond the scope.
So what’s it good for?
Guardian provides a mechanism for verifying previously asserted claims that
someone is who they say they are. Do this for browser based, api, channel,
socket communications or just because you can. The initial login is trivial,
it’s the other parts of the system where things get interesting.
Since Guardian is based on JWT, you can share the tokens with other systems that
you trust. The same shared secret will allow another system to verify the token
which is great for S2S systems. Your Elixir application can mint the credentials
(JWT) and other systems can verify them without a call to your Elixir
application, or they can mint credentials and have them used by your Elixir app.
Screw language differences.
Ok so lets see it then
I’m going to pull the code from my demo application: PhoenixGuardian.
Configuration
Add Guardian to your mix.deps:
defp deps do
[
# ...
{:guardian, "~>0.6.0"},
# ...
]
end
Guardian relies on Joken for it’s JWTs. Guardian will bring it in, but you’ll
need to configure it.
config :joken, config_module: Guardian.JWT
config :guardian, Guardian,
issuer: "MyApp",
ttl: { 30, :days },
verify_issuer: true,
secret_key: "lksdjowiurowieurlkjsdlwwer",
serializer: PhoenixGuardian.GuardianSerializer
A couple of things to note.
- Jokens
config_module
should be set to Guardian.JWT
verify_issuer
Set this to true if you want to only accept tokens generated by yourself (even if another app has your secret)
- Please have different
secret_key
s per environment!
Guardian.Serializer
You’ll need the serializer so your app can serialize into and out of the token.
Don’t worry, this is Elixir, they’re easy.
defmodule PhoenixGuardian.GuardianSerializer do
@behaviour Guardian.Serializer
alias PhoenixGuardian.Repo
alias PhoenixGuardian.User
def for_token(user = %User{}), do: { :ok, "User:#{user.id}" }
def for_token(_), do: { :error, "Unknown resource type" }
def from_token("User:" <> id), do: { :ok, Repo.get(User, String.to_integer(id)) }
def from_token(_), do: { :error, "Unknown resource type" }
end
Need to support different model types? Just add a pattern match in your serializer!
So, at this point, we’re setup to use Guardian, we just need to decide where
and how we’re going to apply it. I’ll show you the pieces.
Plug
Guardian comes with Plug integration. I’m going to focus on Phoenix but any plug
will work.
There are three phases to Guardians plug integration.
- Verifying the token
- Loading the resource
- Requireing a verified token
pipeline :browser_session do
plug Guardian.Plug.VerifySession # looks in the session for the token
plug Guardian.Plug.LoadResource
end
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader # Looks in the Authorization header for the token
plug Guardian.Plug.LoadResource
end
These two pipelines will verify the token (if present) and load the resource if
there was a verified token found. If the token isn’t there or is invalid,
nothing bad happens, the load resource won’t do anything.
When we want to ensure that someone is authenticated we can ensure they have a
verified token.
defmodule PhoenixGuardian.UserController do
use PhoenixGuardian.Web, :controller
alias PhoenixGuardian.User
plug Guardian.Plug.EnsureAuthenticated, %{ on_failure: { PhoenixGuardian.SessionController, :new } } when not action in [:new, :create]
# ....
end
Ok, so there’s some stuff going on there. Lets break it down.
The Guardian.Plug.EnsureAuthenticated checks to make sure there was a valid token
found. If it finds one we move on.
If the plug cannot find a verified token for the connection, it calls the
on_failure
function. This function should be arity 2 and receive a Plug.Conn.t and it’s params. It’s up to this function to handle what should happen when things go south.
We could have put this plug in the pipeline, the only reason I didn’t do that
for this controller was because I wanted more control over the actions it fires
for, hence the when not action
stuff.
Signing In.
Ok so, this is all good and well. We’ve configured it, setup a serializer, and
created our pipelines, how to sign in?
def create(conn, %{"user" => user_params}) do
changeset = User.create_changeset(%User{}, user_params)
if changeset.valid? do
user = Repo.insert(changeset)
conn
|> put_flash(:info, "User created successfully.")
|> Guardian.Plug.sign_in(user, :token)
|> redirect(to: user_path(conn, :index))
else
render(conn, "new.html", changeset: changeset)
end
end
See that tiny line in the middle there. Guardian.Plug.sign_in(user, :csrf)
.
That’s it. Once you do that, your token is generated, pumped into the connection
and session and off you go.
The :csrf
determines the tokens type (stored in the :aud
field). This can be
anything you want it to be (e.g. ‘token’, ‘csrf’, ‘api’, ‘oauth’ etc).
Logout
Guardian.Plug.logout(conn)
|> redirect_or_something
Channels
Ok so, I did say you could use this for channels right. Here it is:
some_html.html
<%= if Guardian.Plug.current_token(@conn) do %>
<meta name='guardian_token' content="<%= Guardian.Plug.current_token(@conn) %>">
<% end %>
some_javascript.js
let socket = new Socket("/ws");
socket.connect();
let guardianToken = jQuery('meta[name="guardian_token"]').attr('content');
let chan = socket.chan("pings", { guardian_token: guardianToken });
phoenix_guardian/user_channel.ex
defmodule PhoenixGuardian.UsersChannel do
use Phoenix.Channel
use Guardian.Channel
def join(_room, %{ claims: claims, resource: resource }, socket), do: { :ok, %{ message: "Joined" }, socket }
def join(room, _, socket), do: { :error, :authentication_required }
def handle_in("ping", _payload, socket) do
user = Guardian.Channel.current_resource(socket)
broadcast socket, "pong", %{ message: "pong", from: user.email }
{ :noreply, socket }
end
def handle_guardian_auth_failure(reason), do: { :error, %{ error: reason } }
end
When Guardian finds a valid token, it extracts the claims and the resource, and
calls join
with them in the map. The keys to pattern match on for
authenticated joins are claims
and resource
.
When Guardian cannot verify the token, it will call handle_guardian_auth_failure
with the reason it failed.
Well, thats a whirlwind tour of Guardian as it stands today. There’s a lot more
to say, but for the first post I think that will do.


Sixteen
Slide the grid squares around so that the numbers end up in consecutive order from the top left corner.
Click on the arrows at the edges of the grid to move a row or column left, right, up or down. The square that falls off the end of the row comes back on the other end.


Add Mapillary Views to Your Carto Map
Enter your geojson in the box below.
- Login at carto.com.
- Click maps in the top right corner near your user icon.
- Click New Map in the top right corner.
- Click Connect Data in the tab bar.
- Drag and drop your downloaded geojson file into the browser window and click the Connect Dataset button.
- Wait for the geojson to import and a map will load.
- Just like any other carto map you’re going to need to select which fields you want to show when a point is clicked on. Click any visibile point on the map and click the select fields link. Make sure that you check the field labeled mapillary_fill.
- Click the publish link in the top right most corner and copy the link in the field labeled CartoDB.js. It has a purple circle with tools in it.
- Paste the link in the following box< /li>


"""Base class defining the file system hook interface."""
from builtins import super
import errno
import posixpath
import shutil
from airflow.hooks.base_hook import BaseHook
from airflow_fs.ports import glob
[docs]class FsHook(BaseHook):
"""Base FsHook defining the FsHook interface and providing some basic
functionality built on this interface.
"""
def __init__(self):
super().__init__(source=None)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.disconnect()
[docs] def disconnect(self):
"""Closes fs connection (if applicable)."""
# Interface methods (should be implemented by sub-classes).
# pylint: disable=missing-docstring
def get_conn(self):
raise NotImplementedError()
[docs] def open(self, file_path, mode='rb'):
"""Returns file_obj for given file path.
:param str file_path: Path to the file to open.
:param str mode: Mode to open the file in.
:returns: An opened file object.
"""
raise NotImplementedError()
[docs] def exists(self, file_path):
"""Checks whether the given file path exists.
:param str file_path: File path.
:returns: True if the file exists, else False.
:rtype: bool
"""
raise NotImplementedError()
[docs] def isdir(self, path):
"""Returns true if the given path points to a directory.
:param str path: File or directory path.
"""
raise NotImplementedError()
[docs] def listdir(self, dir_path):
"""Lists names of entries in the given path."""
raise NotImplementedError()
[docs] def mkdir(self, dir_path, mode=0o755, exist_ok=True):
"""Creates the directory, without creating intermediate directories."""
raise NotImplementedError()
[docs] def rm(self, file_path):
"""Deletes the given file path.
:param str file_path: Path to file:
"""
raise NotImplementedError()
[docs] def rmtree(self, dir_path):
"""Deletes given directory tree recursively.
:param str dir_path: Path to directory to delete.
"""
raise NotImplementedError()
@staticmethod
def _raise_dir_exists(dir_path):
raise IOError(errno.EEXIST,
'Directory exists: {!r}'.format(dir_path))
# General utility methods built on the above interface methods.
# These methods can be overridden in sub-classes if more efficient
# implementations are available for a specific file system.
[docs] def makedirs(self, dir_path, mode=0o755, exist_ok=True):
"""Creates directory, creating intermediate directories if needed.
:param str dir_path: Path to the directory to create.
:param int mode: Mode to use for directory (if created).
:param bool exist_ok: Whether the directory is already allowed to exist.
If false, an IOError is raised if the directory exists.
"""
head, tail = posixpath.split(dir_path)
if not tail:
head, tail = posixpath.split(head)
if head and tail and not self.exists(head):
try:
self.makedirs(head, mode=mode, exist_ok=exist_ok)
except FileExistsError:
# Defeats race condition when another thread created the path
pass
current_dir = posixpath.curdir
if isinstance(tail, bytes):
current_dir = bytes(posixpath.curdir, 'ASCII')
if tail == current_dir: # xxx/newdir/. exists if xxx/newdir exists
return
try:
self.mkdir(dir_path, mode=mode, exist_ok=exist_ok)
except OSError:
# Cannot rely on checking for EEXIST, since the operating system
# could give priority to other errors like EACCES or EROFS
if not exist_ok or not self.isdir(dir_path):
raise
[docs] def walk(self, root):
"""Directory tree generator, similar to os.walk."""
sub_dirs, files = [], []
for item in self.listdir(root):
full_path = posixpath.join(root, item)
if self.isdir(full_path):
sub_dirs.append(item)
else:
files.append(item)
yield root, sub_dirs, files
for sub_dir in sub_dirs:
for entry in self.walk(posixpath.join(root, sub_dir)):
yield entry
[docs] def glob(self, pattern, recursive=False):
"""Return a list of paths matching a pathname pattern."""
return glob.glob(pattern, recursive=recursive, hook=self)
# Methods for copying files between hooks.
[docs] def copy(self, src_path, dest_path, src_hook=None):
"""Copies file(s) into the hooks file system.
By default, source files are assumed to be on the same file system as the
destination (the hooks file system). To copy between different file systems
or file systems in different locations, a source file hook can be provided
using the `src_hook` argument.
"""
# TODO: Allow short circuiting when copying within the same filesystem
# with the same connection details?
with src_hook.open(src_path, "rb") as src_file, \
self.open(dest_path, "wb") as dest_file:
shutil.copyfileobj(src_file, dest_file)
[docs] def copy_fileobj(self, file_obj, dest_path):
"""Copies a file object into the hooks file system."""
with self.open(dest_path, "wb") as dst_file:
shutil.copyfileobj(file_obj, dst_file)
class NotSupportedError(NotImplementedError):
"""Exception that can be raised by FsHooks if they don't support
a given operation.
"""


Client - Myself
Period - September 2018
Could Be Worse
An early project of mine, the goal was to create an online magazine, write the content for it, and make it responsive. The simplicity of the site was done to draw attention to the content, which in this case is the articles.
The bottom navigation was to remove unnecessary clutter along the page, and to make sure people read the articles before proceeding to the next one. Since there are only 3 articles written for the page, this concise navigation method means the site is easy to navigate.
Click here to view full site.


Home
Page
This page not use master, Render code:
goview.Render(200, "page.html", goview.M{})
"page.html" - add extension ".html" will render without master.
{{include "layouts/footer"}}


1: /* 2: * Copyright 2001-2009 Stephen Colebourne 3: * 4: * Licensed under the Apache License, Version 2.0 (the "License"); 5: * you may not use this file except in compliance with the License. 6: * You may obtain a copy of the License at 7: * 8: * http://www.apache.org/licenses/LICENSE-2.0 9: * 10: * Unless required by applicable law or agreed to in writing, software 11: * distributed under the License is distributed on an "AS IS" BASIS, 12: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13: * See the License for the specific language governing permissions and 14: * limitations under the License. 15: */ 16: package org.joda.time.chrono; 17: 18: import java.util.HashMap; 19: import java.util.Map; 20: 21: import org.joda.time.Chronology; 22: import org.joda.time.DateTime; 23: import org.joda.time.DateTimeConstants; 24: import org.joda.time.DateTimeField; 25: import org.joda.time.DateTimeZone; 26: import org.joda.time.field.SkipDateTimeField; 27: 28: /** 29: * Implements the Coptic calendar system, which defines every fourth year as 30: * leap, much like the Julian calendar. The year is broken down into 12 months, 31: * each 30 days in length. An extra period at the end of the year is either 5 32: * or 6 days in length. In this implementation, it is considered a 13th month. 33: *
 34: * Year 1 in the Coptic calendar began on August 29, 284 CE (Julian), thus 35: * Coptic years do not begin at the same time as Julian years. This chronology 36: * is not proleptic, as it does not allow dates before the first Coptic year. 37: *
 38: * This implementation defines a day as midnight to midnight exactly as per 39: * the ISO chronology. Some references indicate that a coptic day starts at 40: * sunset on the previous ISO day, but this has not been confirmed and is not 41: * implemented. 42: *
 43: * CopticChronology is thread-safe and immutable. 44: * 45: * @see Wikipedia 46: * @see JulianChronology 47: * 48: * @author Brian S O'Neill 49: * @since 1.0 50: */ 51: public final class CopticChronology extends BasicFixedMonthChronology { 52: 53: /** Serialization lock */ 54: private static final long serialVersionUID = -5972804258688333942L; 55: 56: /** 57: * Constant value for 'Anno Martyrum' or 'Era of the Martyrs', equivalent 58: * to the value returned for AD/CE. 59: */ 60: public static final int AM = DateTimeConstants.CE; 61: 62: /** A singleton era field. */ 63: private static final DateTimeField ERA_FIELD = new BasicSingleEraDateTimeField("AM"); 64: 65: /** The lowest year that can be fully supported. */ 66: private static final int MIN_YEAR = -292269337; 67: 68: /** The highest year that can be fully supported. */ 69: private static final int MAX_YEAR = 292272708; 70: 71: /** Cache of zone to chronology arrays */ 72: private static final Map<DateTimeZone, CopticChronology[]> cCache = new HashMap<DateTimeZone, CopticChronology[]>(); 73: 74: /** Singleton instance of a UTC CopticChronology */ 75: private static final CopticChronology INSTANCE_UTC; 76: static { 77: // init after static fields 78: INSTANCE_UTC = getInstance(DateTimeZone.UTC); 79: } 80: 81: //----------------------------------------------------------------------- 82: /** 83: * Gets an instance of the CopticChronology. 84: * The time zone of the returned instance is UTC. 85: * 86: * @return a singleton UTC instance of the chronology 87: */ 88: public static CopticChronology getInstanceUTC() { 89: return INSTANCE_UTC; 90: } 91: 92: /** 93: * Gets an instance of the CopticChronology in the default time zone. 94: * 95: * @return a chronology in the default time zone 96: */ 97: public static CopticChronology getInstance() { 98: return getInstance(DateTimeZone.getDefault(), 4); 99: } 100: 101: /** 102: * Gets an instance of the CopticChronology in the given time zone. 103: * 104: * @param zone the time zone to get the chronology in, null is default 105: * @return a chronology in the specified time zone 106: */ 107: public static CopticChronology getInstance(DateTimeZone zone) { 108: return getInstance(zone, 4); 109: } 110: 111: /** 112: * Gets an instance of the CopticChronology in the given time zone. 113: * 114: * @param zone the time zone to get the chronology in, null is default 115: * @param minDaysInFirstWeek minimum number of days in first week of the year; default is 4 116: * @return a chronology in the specified time zone 117: */ 118: public static CopticChronology getInstance(DateTimeZone zone, int minDaysInFirstWeek) { 119: if (zone == null) { 120: zone = DateTimeZone.getDefault(); 121: } 122: CopticChronology chrono; 123: synchronized (cCache) { 124: CopticChronology[] chronos = cCache.get(zone); 125: if (chronos == null) { 126: chronos = new CopticChronology[7]; 127: cCache.put(zone, chronos); 128: } 129: try { 130: chrono = chronos[minDaysInFirstWeek - 1]; 131: } catch (ArrayIndexOutOfBoundsException e) { 132: throw new IllegalArgumentException 133: ("Invalid min days in first week: " + minDaysInFirstWeek); 134: } 135: if (chrono == null) { 136: if (zone == DateTimeZone.UTC) { 137: // First create without a lower limit. 138: chrono = new CopticChronology(null, null, minDaysInFirstWeek); 139: // Impose lower limit and make another CopticChronology. 140: DateTime lowerLimit = new DateTime(1, 1, 1, 0, 0, 0, 0, chrono); 141: chrono = new CopticChronology 142: (LimitChronology.getInstance(chrono, lowerLimit, null), 143: null, minDaysInFirstWeek); 144: } else { 145: chrono = getInstance(DateTimeZone.UTC, minDaysInFirstWeek); 146: chrono = new CopticChronology 147: (ZonedChronology.getInstance(chrono, zone), null, minDaysInFirstWeek); 148: } 149: chronos[minDaysInFirstWeek - 1] = chrono; 150: } 151: } 152: return chrono; 153: } 154: 155: // Constructors and instance variables 156: //----------------------------------------------------------------------- 157: /** 158: * Restricted constructor. 159: */ 160: CopticChronology(Chronology base, Object param, int minDaysInFirstWeek) { 161: super(base, param, minDaysInFirstWeek); 162: } 163: 164: /** 165: * Serialization singleton. 166: */ 167: private Object readResolve() { 168: Chronology base = getBase(); 169: int minDays = getMinimumDaysInFirstWeek(); 170: minDays = (minDays == 0 ? 4 : minDays); // handle rename of BaseGJChronology 171: return base == null ? 172: getInstance(DateTimeZone.UTC, minDays) : 173: getInstance(base.getZone(), minDays); 174: } 175: 176: // Conversion 177: //----------------------------------------------------------------------- 178: /** 179: * Gets the Chronology in the UTC time zone. 180: * 181: * @return the chronology in UTC 182: */ 183: public Chronology withUTC() { 184: return INSTANCE_UTC; 185: } 186: 187: /** 188: * Gets the Chronology in a specific time zone. 189: * 190: * @param zone the zone to get the chronology in, null is default 191: * @return the chronology 192: */ 193: public Chronology withZone(DateTimeZone zone) { 194: if (zone == null) { 195: zone = DateTimeZone.getDefault(); 196: } 197: if (zone == getZone()) { 198: return this; 199: } 200: return getInstance(zone); 201: } 202: 203: //----------------------------------------------------------------------- 204: long calculateFirstDayOfYearMillis(int year) { 205: // Java epoch is 1970-01-01 Gregorian which is 1686-04-23 Coptic. 206: // Calculate relative to the nearest leap year and account for the 207: // difference later. 208: 209: int relativeYear = year - 1687; 210: int leapYears; 211: if (relativeYear <= 0) { 212: // Add 3 before shifting right since /4 and >>2 behave differently 213: // on negative numbers. 214: leapYears = (relativeYear + 3) >> 2; 215: } else { 216: leapYears = relativeYear >> 2; 217: // For post 1687 an adjustment is needed as jan1st is before leap day 218: if (!isLeapYear(year)) { 219: leapYears++; 220: } 221: } 222: 223: long millis = (relativeYear * 365L + leapYears) 224: * (long)DateTimeConstants.MILLIS_PER_DAY; 225: 226: // Adjust to account for difference between 1687-01-01 and 1686-04-23. 227: 228: return millis + (365L - 112) * DateTimeConstants.MILLIS_PER_DAY; 229: } 230: 231: //----------------------------------------------------------------------- 232: int getMinYear() { 233: return MIN_YEAR; 234: } 235: 236: //----------------------------------------------------------------------- 237: int getMaxYear() { 238: return MAX_YEAR; 239: } 240: 241: //----------------------------------------------------------------------- 242: long getApproxMillisAtEpochDividedByTwo() { 243: return (1686L * MILLIS_PER_YEAR + 112L * DateTimeConstants.MILLIS_PER_DAY) / 2; 244: } 245: 246: //----------------------------------------------------------------------- 247: protected void assemble(Fields fields) { 248: if (getBase() == null) { 249: super.assemble(fields); 250: 251: // Coptic, like Julian, has no year zero. 252: fields.year = new SkipDateTimeField(this, fields.year); 253: fields.weekyear = new SkipDateTimeField(this, fields.weekyear); 254: 255: fields.era = ERA_FIELD; 256: fields.monthOfYear = new BasicMonthOfYearDateTimeField(this, 13); 257: fields.months = fields.monthOfYear.getDurationField(); 258: } 259: } 260: 261: }
| ID | Line | Type | Detected |
|---|---|---|---|
| 2625 | 98 | Replace a constant (Replace 4 with 5(INT)) | |
| 2624 | 98 | Replace a constant (Replace 4 with 0(INT)) | |
| 2623 | 98 | Replace a constant (Replace 4 with 3(INT)) | |
| 2622 | 98 | Remove method call | |
| 2626 | 98(1) | Remove method call | |
| 2629 | 108 | Replace a constant (Replace 4 with 5(INT)) | |
| 2627 | 108 | Replace a constant (Replace 4 with 3(INT)) | |
| 2628 | 108 | Replace a constant (Replace 4 with 0(INT)) | |
| 2630 | 108 | Remove method call | |
| 2631 | 119 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2632 | 120 | Remove method call | |
| 2633 | 124 | Remove method call | |
| 2634 | 125 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2635 | 126 | Replace a constant (Replace 7 with 0(INT)) | |
| 2637 | 126 | Replace a constant (Replace 7 with 8(INT)) | |
| 2636 | 126 | Replace a constant (Replace 7 with 6(INT)) | |
| 2638 | 127 | Remove method call | |
| 2639 | 130 | Replace a constant (Replace 1 with 2(INT)) | |
| 2640 | 130 | Replace a constant (Replace 1 with 0(INT)) | |
| 2641 | 130 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 2642 | 132 | Remove method call | |
| 2643 | 132(1) | Remove method call | |
| 2644 | 132(2) | Remove method call | |
| 2645 | 135 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2646 | 136 | Negate jump condition (Replace IF_ACMPNE with IF_ACMPEQ) | |
| 2647 | 140 | Replace a constant (Replace 1 with 2(INT)) | |
| 2648 | 140 | Replace a constant (Replace 1 with 0(INT)) | |
| 2650 | 140(1) | Replace a constant (Replace 1 with 0(INT)) | |
| 2649 | 140(1) | Replace a constant (Replace 1 with 2(INT)) | |
| 2652 | 140(2) | Replace a constant (Replace 1 with 0(INT)) | |
| 2651 | 140(2) | Replace a constant (Replace 1 with 2(INT)) | |
| 2653 | 140(3) | Replace a constant (Replace 0 with 1(INT)) | |
| 2654 | 140(3) | Replace a constant (Replace 0 with -1(INT)) | |
| 2656 | 140(4) | Replace a constant (Replace 0 with -1(INT)) | |
| 2655 | 140(4) | Replace a constant (Replace 0 with 1(INT)) | |
| 2657 | 140(5) | Replace a constant (Replace 0 with 1(INT)) | |
| 2658 | 140(5) | Replace a constant (Replace 0 with -1(INT)) | |
| 2659 | 140(6) | Replace a constant (Replace 0 with 1(INT)) | |
| 2660 | 140(6) | Replace a constant (Replace 0 with -1(INT)) | |
| 2661 | 141 | Remove method call | |
| 2662 | 145 | Remove method call | |
| 2663 | 146 | Remove method call | |
| 2664 | 149 | Replace a constant (Replace 1 with 2(INT)) | |
| 2665 | 149 | Replace a constant (Replace 1 with 0(INT)) | |
| 2666 | 149 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 2667 | 168 | Remove method call | |
| 2668 | 169 | Remove method call | |
| 2671 | 170 | Replace a constant (Replace 4 with 0(INT)) | |
| 2672 | 170 | Replace a constant (Replace 4 with 5(INT)) | |
| 2670 | 170 | Replace a constant (Replace 4 with 3(INT)) | |
| 2669 | 170 | Negate jump condition (Replace IFNE with IFEQ) | |
| 2673 | 171 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2674 | 171 | Remove method call | |
| 2675 | 171(1) | Remove method call | |
| 2676 | 171(2) | Remove method call | |
| 2677 | 194 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2678 | 195 | Remove method call | |
| 2680 | 197 | Negate jump condition (Replace IF_ACMPNE with IF_ACMPEQ) | |
| 2679 | 197 | Remove method call | |
| 2681 | 200 | Remove method call | |
| 2683 | 209 | Replace a constant (Replace 1687 with 0(INT)) | |
| 2684 | 209 | Replace a constant (Replace 1687 with 1686(INT)) | |
| 2682 | 209 | Replace a constant (Replace 1687 with 1688(INT)) | |
| 2685 | 209 | Replace arithmetic operator (Replace ISUB with IADD) | |
| 2686 | 211 | Negate jump condition (Replace IFGT with IFLE) | |
| 2688 | 214 | Replace a constant (Replace 3 with 0(INT)) | |
| 2689 | 214 | Replace a constant (Replace 3 with 4(INT)) | |
| 2687 | 214 | Replace a constant (Replace 3 with 2(INT)) | |
| 2692 | 214(1) | Replace a constant (Replace 2 with 1(INT)) | |
| 2691 | 214(1) | Replace a constant (Replace 2 with 3(INT)) | |
| 2693 | 214(1) | Replace a constant (Replace 2 with 0(INT)) | |
| 2690 | 214 | Replace arithmetic operator (Replace IADD with ISUB) | |
| 2694 | 214(1) | Replace arithmetic operator (Replace ISHR with ISHL) | |
| 2695 | 216 | Replace a constant (Replace 2 with 3(INT)) | |
| 2697 | 216 | Replace a constant (Replace 2 with 0(INT)) | |
| 2696 | 216 | Replace a constant (Replace 2 with 1(INT)) | |
| 2698 | 216 | Replace arithmetic operator (Replace ISHR with ISHL) | |
| 2700 | 218 | Negate jump condition (Replace IFNE with IFEQ) | |
| 2699 | 218 | Remove method call | |
| 2703 | 223 | Replace a constant (Replace 365 with 0(LONG)) | |
| 2701 | 223 | Replace a constant (Replace 365 with 366(LONG)) | |
| 2702 | 223 | Replace a constant (Replace 365 with 364(LONG)) | |
| 2707 | 223(1) | Replace a constant (Replace 86400000 with 86400001(LONG)) | |
| 2708 | 223(1) | Replace a constant (Replace 86400000 with 86399999(LONG)) | |
| 2706 | 223(1) | Replace a constant (Replace 86400000 with 0(LONG)) | |
| 2704 | 223 | Replace arithmetic operator (Replace LMUL with LADD) | |
| 2705 | 223(1) | Replace arithmetic operator (Replace LADD with LSUB) | |
| 2709 | 223(2) | Replace arithmetic operator (Replace LMUL with LADD) | |
| 2710 | 228 | Replace a constant (Replace<PHONE_NUMBER>0 with<PHONE_NUMBER>9(LONG)) | |
| 2711 | 228 | Replace a constant (Replace<PHONE_NUMBER>0 with 0(LONG)) | |
| 2712 | 228 | Replace a constant (Replace<PHONE_NUMBER>0 with<PHONE_NUMBER>1(LONG)) | |
| 2713 | 228 | Replace arithmetic operator (Replace LADD with LSUB) | |
| 2714 | 233 | Replace a constant (Replace -292269337 with 0(INT)) | |
| 2715 | 233 | Replace a constant (Replace -292269337 with -292269336(INT)) | |
| 2716 | 233 | Replace a constant (Replace -292269337 with -292269338(INT)) | |
| 2717 | 238 | Replace a constant (Replace 292272708 with 0(INT)) | |
| 2718 | 238 | Replace a constant (Replace 292272708 with 292272707(INT)) | |
| 2719 | 238 | Replace a constant (Replace 292272708 with 292272709(INT)) | |
| 2722 | 243 | Replace a constant (Replace<PHONE_NUMBER>0000 with<PHONE_NUMBER>0001(LONG)) | |
| 2720 | 243 | Replace a constant (Replace<PHONE_NUMBER>0000 with 0(LONG)) | |
| 2721 | 243 | Replace a constant (Replace<PHONE_NUMBER>0000 with<PHONE_NUMBER>9999(LONG)) | |
| 2724 | 248 | Negate jump condition (Replace IFNONNULL with IFNULL) | |
| 2723 | 248 | Remove method call | |
| 2725 | 249 | Remove method call | |
| 2726 | 256 | Replace a constant (Replace 13 with 0(INT)) | |
| 2728 | 256 | Replace a constant (Replace 13 with 12(INT)) | |
| 2727 | 256 | Replace a constant (Replace 13 with 14(INT)) | |
| 2729 | 257 | Remove method call |


| Name: smt. Radhika.s | Reg No: 2-7SMHC17 |
|---|---|
| Age / Sex: 38 yrs..f | Contact No:9060937722 |
| Marital Status:MARRIED – 15yrs | Date:7/7/17 |
| Occupation:housewife. Ba arts | Dr. PJFP |
Address: Blore – 15 yrs |
DIAGNOSIS- |
Joint pain since 1month. <sitting on floor, on waking cant walk due to pain.. Knees and fingers and ankle pain. swelling and feels hot on knees and ankles. >hot water. <cold
Weight loss 8 kgs 2-3 months.
Dm since 3 years. Found out by having some vaginal infection. Gynac suggested fr a test and came to know tht she is diabetic.
Itching vagina <coition and after coition fr 2-3days. Light burnin urination on and off > scratching. During menses <burning urination. Night urine 2-3 times.
Constipation. Will get motion only if takes sugar tablet.
Headache 15 days once. Whole headache.
Lmp: 28/6/17. 5 day flow. 3 pads /day. First 3 days. Nausea.
Bp: 130/70mmhg
Hb-6.3 % 7/4/17.
Fasting – 162mg/dl
FAMILY H/O:
DAD: DM DIED DUE TO GANGRENE.
MOM: ?THYROID DYSFUNCTION.
ELDER SIS: dm.
PAST H/O:
2002 MARRIAGE. 2003 CONCEIVED. 5 MONTH ABORTION AFTER THAT HAD 3 TIMES ABORTION. BABY NOT FORMING WELL . TOOK HEPARIN FR 9 MONTH
Tb 2000 – took 9 months rx.
Rx:
1) rhus tox 200 4-4-4-4
2) helonias 200 – 4 doses
3) sygizuim Q – 15-15-15-15 drops.
4) AC.NIT 200 – 2 DOSES – WEEKLY ONCE.
22/7/17: no relief from pain. fbs: 142 mg/dl. Ppbs: 198mg/dl. Vaginal infection feels better. 2-3 days has cold. First started with left knee then to right. Numbness in right middle 3 fingers feels numbness more in the night only. > cold water.cant sit down at all. needs grip to sit down due to pain.
Rx:
1.rt 10m
2.led 200.
3. lyco 200 – 4 doses alt days with water.
Carc 1m
21/8/17: feels pain slightly inc than b4 but not to tht extent whr she required to take med alorx. Numbness better in fingers ocassionlly getz it. Vaginal infection. No burning urination. Headache not getting now. Says has always been very anaemic due to heavy bleeding. after marriage and deliveries feels flow has reduced. First day pain in back for menses. Very painful then.
Rx:
1.polyporus pinicola 200 – 4-0-4 disc with water
2.eup perf 200 – 4-0-4 disc with water
3. sepia 200 – 4 doses. Weekly once wit water.
4. medo 200 – 2 doses – 15 days once with water.
22/9/17: AS LONG AS MED WAS THER NO PAIN.  FEELS BETTER WITH URINATION. PAINS. BUT INFECTION NO CHANGE. LMP: 4 DAYS AFTER VINAYAKA CHAVITHI. MOTION CLEAR.
RX:
CHINA 1M – 4 PILLS – MNG B/FOOD WATER
polyporus pinicola 200 – 4-0-4 disc with water
ACID NITRICUM 1M/ MEDO 1M/THUJA200 – 4 DOSES – WEEKLY ONCE – B/FOOD WITH WATER MNG..
ZINC MET 200 – DISC 4-0-4 WITH WATER B/FOOD.
SYZIZIUM Q – 10-10-10 DROPS A/FOOD.
30/11/17: NO JOINT PAIN . ABLE TO WALK. FROM ONE MONTH NO TABLTS. SLEEP A BIT DISTURBED. THINKING DUE TO HER FAMILY HEALTH N OTHER PBMS. NO PULLING PAIN IN FINGERS ALSO. HAS SUGAR , URINE INFECTION. ITHCING. COLD WATER WASHING FEELS BETTER. FEELING THAT HER MOTHER IS VERY DISTUBED DUE TO .
RX:
FERR PHOS 12 X 4-4-4-4
MERC SOL 1M / MEDO 10 M/ SULPHUR 1M – 1 DRAM PILLS 4-4-4
RUBRUM 15 . 1 DOSE NIGHT B/FOOD.
AVENA Q+SYSZQ 10-10-10-10 DROPS A/FOOD WATER.
23/1/18:burning more after coition only after coition then stays till 3-4 days. Heavy bleeding whenever menses. 4 /day pads. Stays for 3 days. 4th n 5th day minimal. Clots < whenever passes urine. Gets motion frequently almost 2-3 times durin menses only off late. Back pain in the lumbar region and sometimes radiates a bit lower. From 2-3 years only has this pbm. If eats any hard substance gets cut on the tongue. Eats raw rice while cleanin likes to eat. slate pencils use to like to eat. now changed to dove soap. Fear that anything may happen to the uterus and may get removed and all. first time when she was 18-19 years she fainted in a temple. Then got to know her hb was low. Then got a blood transfusion. Numbness if she eats sugar. 3 months baby she fell down from bed didn’t cry doc had to beat her a lot on back to make her cry.
Before marriage 21 years of age got wisdom tooth . couldn’t breathe then at all. got tooth on tooth said there was a lot of pressure on the structures beside. After removing the impacted tooth she felt better but thr was no further cure. Cries a lot. Gets a lot of pain in the heart region says she feels left hand pains. She liked to work but she didn’t get credit so quit saying why shd she burden herself and work. Gets nausea with iron tablets. No interest in sex. Feels should be more neat. If she has interest will have no pain. no interest with neat. Feels its wrong and only to have kids it is important otherwise no need. Feeling pain for everything. Dryness vagina then. Drank on breastfeeding only fr 3 months. After that only top feeds. Delayed in walking
Rx:
Lecithin 30 – disc 4-4-4-4
Ferr phos 12 x 4-4-4-4
Tuberculinum 1m – 3 doses 5 days once b/food.
Nat mur 1m – 2 doses – 1 dose bfood weekly.
24/11/18: lmp: 18/11/18. Same no change in bleeding. Burning vagina is more than itching. Must use ointment. Fbs is 140 ; ppbs -240 mgdl. Hb- 6gm%. No weakness no hunger infact feels less hungry. No profuse urination no exces sweating.
Rx:
First one month
Carc 0/1 2 pills twice b/food alternate days for one month.
Acid phos 1m disc 3-0-3 a/food.
Thlaspi bursa pastoris 10-10-10 drops a/food.
Ignatia 1m – 4 doses – weekly before food.
Syzizium Q 10-10-10 drops a/food.
Rheumagic oil
Pl doses 30- 1 dose nt b/food.
2nd month:
Continue 2,3,4,5,7.
Penta phos tabs 2-0-2
28/12/18: hb- 5.4 gm%. Morning vomiting sensation. Pica there. Neatness more. Obsessed. Cant eat others engili. Even husband. Not even kids. Now a days cant eat in hotels also. Feeling very irritated. Bleeding 5 days . 4pads /day. Fr 3days. 4 n 5 th day less. Backpain during menses but still reduced after my med last year now started to get again. Very fixed in the ideas will fast. Religious obsession. Milk aversion.
Rx:
Lecithin 200 – 4-4-4
Alfalfa avenaQ ginseng– 15-15-15 drops a/food water.
Lachesis 1m – 2 doses – water mng
Carcinosin 1m – mng 1 tab b/food.
12/1/19: lmp: dec 13th 2018. Bleeding better. 1 week cough and cold. Morning sickness there.
Rx:
Lach 1m – 2 doses – weekly.
Ferr phos 6x 4-4-4-4
Pl 15 – 1 dose night b/food.
Benzenum 200 – disc 4-0-4.
Disc 4—0-4.
19/2/19: vomiting sensation not there. Lmp: 20/1/19. Bleeding normal. Night no sleep frm 5 days. Itching reduced this time in genitals. Wt: 61.2kg.
Rx:
Lach 1m – 4-4-4 for 4 days alternate weeks.
Ferr phos 6x 4-4-4
Pl 30 – 1 dose night b/food.
Benzenum 200 – disc 4-0-4.
Disc 4-0-4. A/food.
28/3/19: VOMITING SENSATION IS NOT THERE. LMP: 25/3/19: SLEEP BETTER. NO ITCHING ALSO.
RX:
Lach 1m – 4-4-4 for 4 days alternate weeks.
Ferr phos 6x 4-4-4
Pl 30 – 1 dose night b/food.
Benzenum 200 – disc 4-0-4.
Disc 4-0-4. A/food.
MEDICINE FOR 2 MONTHS.


Fonts
«When typography is on point, words become images»
- Shawn Lukas
ROBOTO
Created by: Christian Robertson, Principal design
MALI
Created by: Cadson Demak, Principal design


News of Damjan-mont
Keep up to date the latest developments,project as well as with the
latest trendsand timber products from out team
Create a New Gazebos
21:48 Monday
Create a Perfect Gazebos
13:40 Friday
Briliant Works in the Bitch
11:28 Wensday
Build a Perfect House in Summer
14:30 Monday
26.02.2019 21:30
Make Gazebos With a perfect Creation and inovation
More off this less hello salamander lied porpoise much over tightly circa horse taped so innocuously outside crud mightily rigorous negative one inside gorilla outside crud mightily rigorous…   More off this less hello salamander lied porpoise much over tightly circa horse taped so innocuously outside crud mightily rigorous negative one inside gorilla…


Navigation
- Getting Started
- Example Apps
- Inital Setup
- Using Models
- Rendering pages with Views and Controllers
- Event System
Building Apps with Flakey.js
Flakey.js is written in CoffeeScript and makes heavy use of it’s Class structure and simulated classical inheritance. As such, it’s easiest to write Flakey.js apps in CoffeeScript, using the Class
and extends
features.
Additionally, throughout the examples in these docs we use eco html templates as views and browserify to take care of bundling dependancies into a single Javascript file. Neither of these are required or part of Flakey.js, but they do work nicely.
Compiling Flakey.js
Requirements
To compile Flakey.js from source, you’ll need to install:
- nodejs
- npm (normally installed with nodejs)
- cake (normally installed with nodejs)
- coffeescript (
npm install -g coffee-script
)
To compile the sample note taking app (example/*), all of the above plus:
- browserify (
npm install browserify
) - eco (
npm install -g eco
)
Build Process
To compile Flakey.js, cd to the root of the repository and run: cake build
. That will concat the files in src/
into flakey.coffee. Then flakey.coffee is compiled into flakey.js, and finally minified into flakey.min.js using Google’s closure compiler.
Working Examples of Flakey.js
Notes
A simple responsive note taking app that stores notes in browser localStorage. Try it or examine the source.
Annotare
Annotare is a simple personal notes wiki designed to be run locally or on a private server. Annotare leverages to make sure that anytime you edit a note, your edits are entirely non-destructive and reversible. You can download or fork it on Github.
Initalizing Flakey.js on page load
Flakey.js requires you do a bit of setup on pageload:
# Alias Flakey's copy of JQuery
$ = Flakey.$
# Get the controller to display first
controllers = require('./controllers')
# This function customizes a few settings, syncs
# our models, and displays the initial controller
$(document).ready () ->
settings = {
container: $('body')
base_model_endpoint: '/api'
}
Flakey.init(settings)
# Sync models
Flakey.models.backend_controller.sync('Note')
note_app = window.note_app = new controllers.MainStack()
note_app.make_active()
The above code comes from the example Note taking application (index.coffee). We’ll go over controllers later, for now the most important part to pay attention to are the settings and the call to Flakey.init
. Here is a list of settings you can customize with Flakey.init
(with its default value in parenthesis).
- diff_text: (true) If true, Flakey will save strings by generating git-like text patches. If false, it will save the entire string in each version. Either way will be transparent to your application, since Flakey takes care of rendering the the patches into a string before loading it into your model. The only time this would make a difference is performance vs. model size.
- container: (undefined) Required. This is the container to use for your app’s controllers. Generally its ok to set it to
$(body)
- read_backend: (‘memory’) This is the storage backend to use for common read operations, generally ‘memory’ works well, and is certainly the fastest. Other available backends are ‘local’ (localStorage), ‘server’ (JSON api, if its enabled), and ‘socketio’ (socketio server interface, if its enabled).
- base_model_endpoint: (null) Setting this option to your JSON api’s base URL enables saving data to the server backend. This is better documented in the Server API docs.
- socketio_server: (null) Set this option to your socket.io server’s URL to enabled realtime model saving/updating (including server push). You can include a namespace (e.g. http://localhost:8080/models) if so desired.
- enabled_local_backend: (true) This option enabled the localStorage backend. Its normally safe to leave this enabled.
Flakey.models
Defining Models
You can define models for your app by extending Flakey.models.Model.
class Note extends Flakey.models.Model
@model_name: 'Note',
@fields: ['id', 'name', 'content']
# This is a class method
@foo: () ->
return "This is a class method"
# These are instance methods
as_markdown: () ->
return this.content
as_html: () ->
# Using the Showdown Markdown -> HTML converter
converter = new Showdown.converter()
return converter.makeHtml(this.content);
As you can see from the code above, defining a model is very simple. Simply create a new class that extends Flakey.models.Model, set it’s model_name parameter to match the name of the class (in this case Note), and set the fields parameter to an array fields for this model. This must include an id field in addition to you data fields.
Creating a new instance
Now that we’ve defined our model, we can start using it. We can instantiate it a new Note like this:
# Using the init field shorthand
grocerys = new Note {
name: "Grocery List"
}
# Not using the shorthand
grocerys = new Note()
grocerys.name = "Grocery List"
grocerys.save()
This creates a new instance of Note and sets its name field to “Grocery List”. Finally we save it. Save a model will generate a diff of each of it’s fields, and push the difference onto the grocerys.versions
array. Then the model is written into each of the activated storage backends.
About storage backends
Storage backends are methods of saving models for later use. By default the memory backend (an object located at window.memcache) and the localStorage backend are enabled. Via settings, you can enable the server (ajax storage) and socketio (realtime server storage with push updates).
When an model instance is saved, it is written to each enabled storage backend. If for some reason saving to a backend fails (like a network interruption), a transaction log is generated and stored in localStorage listing in order the transactions which failed. When ever a new transaction is requested, a backend will check it’s log for any pending transactions. If some exist, it will push the new transaction onto the end of the array and attempt to perform the first transaction. If it succeeds, it continues until either another failure or the log is empty.
At page load, it’s important to sync each of the storage backends. This is done by calling Flakey.models.backend_controller.sync('Note')
where the string parameter is the name of your model. This should be called once for each of the models in you app, just after you call Flakey.init(settings)
. Model sync will try to execute any pending log transactions, and then will compare and sync the objects stored in each. This makes it possible to use a volatile backend (like ‘memory’) for read actions, thereby reducing server traffic.
Version History
First lets add some data so that we have a history to play with:
# Create a new revision on grocerys
grocerys.content = "# Grocery List
- Milk
- Eggs"
grocerys.save()
# Add another item to the list
grocerys.content = "# Grocery List
- Milk
- Eggs
- Cheese"
grocerys.save()
Now that we have a few versions, we can start to use nifty features of Flakey.js:
# Get a view of grocerys to before we added 'cheese' to the list
# inital save == version 0, so we want version 1
i = 1
time = new Date(note.versions[i].time)
rev = grocerys.evolve(grocerys.versions[i].version_id)
console.log time # The timestamp of when this version was created
console.log rev.name # "Grocery List"
console.log rev.content # "# Grocery List
# - Milk
# - Eggs"
That code lets us non-destructively look at a model instance’s past without altering the actual model. What if we want to completely destroy the model current state and rollback to the last version? That’s even easier:
# Destroy the latest version
# rollback() can accept an integer (rollback N versions) or a
# version_id (rollback to that version)
grocerys.rollback(1)
This snippet pops the latest version from the array and writes it to the enabled storage backends. Please note: Calling rollback() is not reversible. It is destructive to any of the versions its deleting, and therefore potentially very dangerous. Please take care when using it.
Flakey.controllers
Controllers
Flakey implements a fairly standard Model-View-Controller architecture, similar to Spine.js, Backbone.js, or Ruby on Rails. Controllers, and their similar cousin Stacks, are how a Flakey app controls what is displayed on the screen and how user actions are routed to event functions. Views, at least from Flakey’s perspective are just HTML templates. Flakey can use any HTML templating system, but in these example’s we’ll use Eco since support for Eco is built into Flakey via Flakey.templates.
The first step in creating a controller is to implement the Flakey.controllers.Controller
class and provide a constructor function.
class NoteSelector extends Flakey.controllers.Controller
constructor: (config) ->
@id = 'note-selector'
@class_name = 'note-selector view'
@actions = {
'click li.note': 'select_note'
}
super(config)
@append ExampleController
@tmpl = Flakey.templates.get_template('selector', require('./templates/selector'))
render: () ->
context = {
selected: @query_params.id,
notes: Note.all()
}
@html @tmpl.render(context)
select_note: (event) =>
@container.children('ul').children('li.note').removeClass('selected')
selected_note = $(event.target)
selected_note.addClass('selected')
Flakey.util.querystring.update({id: selected_note.attr('id')}, merge = true)
event.preventDefault()
In this example, we create a new controller called NoteSelector
. Within the constructor method, we set several important attributes:
@id
corresponds to the id attribute on the controller’s div element.@class_name
corresponds to the className attribute on the controller’s div element.@actions
is a map where the key is a JQuery action and element selector separated by a space. The value is a string containing the name of the method to call when the event is triggered.@append
is a useful feature that allows us to attach another controller to this controller. Whenever the NoteSelector controller is made active, so are any appended controllers; the same goes for when NoteSelector is made passive.
Additionally, to save processing time in the future, the constructor get’s the Eco template we’ll use for this controller and save it as @tmpl
. The render method is the only other method your controller has to implement. It shouldn’t take any parameters and doesn’t need to return anything; the @render method’s only purpose is to render HTML and then modify the controller’s div attribute’s html. This is most easily accomplished by calling the built-in @html() method and passing in the desired html string. In the case above, the render function builds a context object, renders HTML using the template we got earlier, and passes it into @html().
The @select_note() method above is an event handler, since we set it as the callback event to the ‘click li.note’ action in the constructor. Because of that, you’ll notice several unique things about @select_note():
- It accepts the event parameter. This is a standard JQuery event object containing useful information like the target element and action.
- It uses the
=>
function definition instead of->
. Using a fat arrow for function definition in CoffeeScript is similar to JQuery’s $.proxy() function, in that it ensures @select_note() will always be called with it’s parent object as its lexical scope. This isn’t strictly necessary for event handler functions, but without it, inside the function@
orthis
will point to the event’s target element rather than an our controller object. Since we need to access attributes of the controller object, we use a fat arrow to retain it’s scope.
Active and Passive states
Controllers are enabled/disabled by calling controller.make_active() and controller.make_passive(), respectively. Its very important to note that Flakey never actually sets CSS properties to show/hide an element. Instead it simply sets either an active or passive class on the container. Additionally, controller.make_active() calls your controllers render method.
Stacks
Stacks are similar to controllers in that they let you control what is displayed on the screen. Stacks, however, don’t directly manage content. Instead they manage a stack of separate controllers to ensure that only one s visible at the same time.
class MainStack extends Flakey.controllers.Stack
constructor: (config) ->
@id = 'main-stack'
@class_name = 'stack'
@controllers = {
'notes': NotesController
'contacts': ContactsController
}
@routes = {
'^/notes$': 'notes',
'^/contacts$': 'contacts'
}
@default = '/notes'
super(config)
The most important parts of this example are the @controllers and @routes objects in our new stack. The @controllers attribute defines aliases for each of the controller classes to be managed by our stack. Notice we’re directly passing in controller classes. There is no need to instantiate them, since the stack will do that for us. Secondly the @routes attribute defines a series of regular expressions tied to our controllers. When the stack is active, these regexps are checked against the browser’s URL hash (window.location.hash). The matching controller (of the default fallback) is then made active, while the rest of the managed controllers are made passive. This is repeated anytime the URL hash changes.
Starting off our app
Now that we have controllers defined, we need to instantiate the top-level controller/stack.
$(document).ready () ->
settings = {
container: $('body')
}
Flakey.init(settings)
# Sync models
Flakey.models.backend_controller.sync('Note')
note_app = window.note_app = new MainStack()
note_app.make_active()
Most of this we’ve seen already; what’s important to this tutorial are the last two lines. That makes a new instance of MainStack and marks it active. In this case, since it’s a stack, it will try to find a controller corresponding to the current URL hash. If it doesn’t find one, it will set the hash to @default, then will check again. Whichever controller it finds will be marked as active, while the rest are marked as passive.
Flakey.events
Flakey.js includes a basic event signaling system to allow subscribing to and generating events by means of an Observer-pattern singleton located at Flakey.events. Flakey.js triggers built-in signals for several common events (model updating, etc), but you can also create and trigger your own signals.
Creating a new event
Flakey.events.register 'map_view_updated', (event, namespace, data) ->
console.log 'The Map View has been updated!'
console.log data # Optional arbitrary data passed in by the trigger
This will register (subscribe) the given function to the signal called "map_view_updated"
. Whenever that signal is triggered, our function will be called along with any other functions registered to this event. In addition to the signal name, you can optionally supply a namespace for your signal. For example, you may want to namespace all signals specific to your app under the name “my_app”. You can do that with:
our_fn = (event, namespace, data) ->
console.log 'The Map View has been updated!'
console.log data # Optional arbitrary data passed in by the trigger
Flakey.events.register 'map_view_updated', our_fn, 'my_app'
Triggering an event
Triggering an event is even simpler than registering an action.
Flakey.events.trigger 'map_view_updated'
To trigger an event within a namespace:
Flakey.events.trigger 'map_view_updated', 'my_app'
Additionally, you may optionally pass in data to be passed to the listening functions like so:
Flakey.events.trigger 'map_view_updated', 'my_app', {id: 42}
Destroying a namespace
If you wish, its possible to completely wipe the slate clean for a namespace, removing all listening functions. You can do that by calling:
Flakey.events.clear 'my_app'
It’s doubtful you’ll ever need to do this, but the ability exists if you ever do.
Flakey built in events
These events are built into the default (“flakey”) namespace.
model_foo_updated
- foo is replaced by the model’s name in lowercase (e.g.model_note_updated
). Called when an instance of the model is saved. Note: This will not be called if a model is saved without having any changes made since the previous save. i.e. Calling Foo.save() twice without making any changes to the models data will only trigger this event once.


_mmy The dummy was trying to touch the gummy, crummy and clammy slime, but it kept slipping away from his fingers.[G|D] Mammy was stirring the jammy in her pot while Jimmys hammy started to sizzle on the stove; she knew it was time for a delicious dinner.[G|D] Mommy was so proud of her little mummy as she watched him play a game of rummy in the garden, even though his hands were scummy.[G|D] She shimmied her way around the room, trying to satisfy her yummy tummy with a sweet whammy, but it was no use.[G|D]


Glastonbury 2020: Beatles legend Paul McCartney announced as Saturday night headliner
He last headlined the festival in 2004
by Robin MurraySir Paul McCartney has been announced as the first headliner for Glastonbury 2020.
The icon dropped a huge hint that he will be performing at the 50th anniversary of the festival with a cryptic tweet on his Twitter this morning.
He posted an image of Philip Glass, Emma Stone and Chuck Berry next to each other, spelling out Glass-Stone-Berry.
And just hours later, the festival tweeted to put an end to the ongoing rumours and confirm his appearance, writing: "We are incredibly excited to announce that Paul McCartney will headline the Pyramid Stage on the Saturday night of Glastonbury 2020."
Festival founder Michael Eavis stoked the rumour mill back in April when he said he hoped Macca would play again, 'hopefully for the 50th.'
And in September the former Beatle added to the speculation on The Zoe Ball Breakfast Show, when he said: "People are saying that it will be good if I did it, so I'm starting to think about whether I can or whether it would be a good thing.
"My kids are saying 'Dad, we've got to talk about Glastonbury' and I think I know what they mean.
"It's starting to become some remote kind of possibility. It's definitely not fixed yet but people are starting to talk about it."
The 77-year-old last headlined the festival in 2004, when he performed a mammoth 33-song set including Wings material, a selection of The Beatles' most timeless releases and solo music.
The Beatles recently re-entered the charts following a reissue of their classic album Abbey Road, and next year will mark five decades since their split, which prompted McCartney's stellar solo career.
Other major acts rumoured to headline the Pilton spectacular, which takes place between June 24 - June 28, include Kendrick Lamar, Taylor Swift and Foals.
The first act to be confirmed was Diana Ross, who was announced for the Sunday afternoon legends slot back in October.
For the latest news in and around Bristol, check back on Bristol Live's homepage.


The Contextual Experience of the Mobile Web
The contextual experience on the web was a talk by Jeff Carouth of Texas A&M University. The ZendCon summary:
The great native apps vs mobile web debate will live on for a little while longer, but more and more we are realizing that we can get the best of both worlds with mobile web apps. However, there is an expectation of context on mobile devices, and ignoring that experience expectation is a mistake. Let's look at the contextual experience of the mobile web.
My summary would be history of developing for a mobile client and the emergence of adaptive design as a solution.
One of the interesting points that he brought up was something that had been going around my office lately as well.
What determines a mobile client?
Meaning an iPad and netbook have the same resolution, which one is mobile? Both? iPad only?
Within CSS3 theres specification for media queries. One of these queries that we use is to base the design on resolution. In doing so you are basing the display on the size of screen. At the outset this seems like a great idea. However, there is a drawback. The design to fit the size doesn't account for data size. You could design a photo heavy site to fit in a 600 wide window but if you don't compensate for data size performance on a 3G network user experience will still suck. So while media queries are part of the answer they are not all of the answer.
To fix the second part, one option discussed was image compression or replacement. For compression there's JS resizing. It works but it is ugly. You look at that code and the processing overhead and cringe.
Then there's responsive images, downloading a small image and replacing it with a higher quality one. This adds overhead and bandwidth. You're download two images for every image on your page. Not ideal.
Ideally this should be done on the server side. The technology and/or programs haven't been written for this yet. You'd need to inspect the client agent and then respond with the appropriate image size and resolution. According to him, there's not a good implementation of this at the moment. However, I think there's vast opportunity for someone to develop such a tool.