mirror of
https://github.com/wassname/cardsforscience.git
synced 2026-06-27 16:14:52 +08:00
Working with webpack
This commit is contained in:
+3
-2
@@ -1,8 +1,9 @@
|
||||
.DS_Store
|
||||
*.sublime*
|
||||
notes
|
||||
|
||||
|
||||
secrets
|
||||
build
|
||||
dist
|
||||
|
||||
# Created by https://www.gitignore.io/api/bower,node,linux
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ button, .badge, .modal-content {
|
||||
|
||||
a, button {
|
||||
transition:all 0.2s;
|
||||
-webkit-transition:all 0.2s; }
|
||||
-webkit-transition:all 0.2s;
|
||||
}
|
||||
|
||||
h1 br {
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
+85
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
var gulp = require('gulp');
|
||||
// var path = require('path');
|
||||
var fs = require('fs');
|
||||
var gutil = require('gulp-util')
|
||||
|
||||
// var source = require('vinyl-source-stream');
|
||||
// var buffer = require('vinyl-buffer');
|
||||
// var del = require('del');
|
||||
// var globby = require('globby');
|
||||
|
||||
var concurrent = require("concurrent-transform");
|
||||
var rename = require('gulp-rename');
|
||||
var awspublish = require('gulp-awspublish');
|
||||
var debug = require('gulp-debug');
|
||||
|
||||
// load in settings
|
||||
var pjson = require('./package.json');
|
||||
var production = (process.env.NODE_ENV === 'production');
|
||||
|
||||
var DEBUG = !production;
|
||||
console.log('Running in DEBUG='+DEBUG+' mode')
|
||||
|
||||
var config = {
|
||||
app_entry: 'client/scripts/main.js',
|
||||
debug: DEBUG,
|
||||
}
|
||||
|
||||
/*
|
||||
Just run webpack
|
||||
*/
|
||||
DEBUG = false
|
||||
var webpack = require('webpack-stream');
|
||||
gulp.task('webpack', function () {
|
||||
|
||||
var webpackConfig = require('./webpack.config.js')
|
||||
console.log('debug: ', webpackConfig.debug);
|
||||
|
||||
return gulp.src(config.app_entry)
|
||||
.pipe(webpack(require('./webpack.config.js')))
|
||||
.pipe(gulp.dest('dist/'));
|
||||
});
|
||||
|
||||
|
||||
/** deploy to s3 using gulp-awspublish
|
||||
* https://github.com/pgherveou/gulp-awspublish
|
||||
**/
|
||||
|
||||
gulp.task('s3', function () {
|
||||
|
||||
// create a new publisher using S3 options
|
||||
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
|
||||
var credentials = JSON.parse(fs.readFileSync('secrets/aws-credentials.json', 'utf8'));
|
||||
var publisher = awspublish.create(credentials);
|
||||
|
||||
// define custom headers
|
||||
var headers = {
|
||||
'Cache-Control': 'max-age=315360000, no-transform, public'
|
||||
// ...
|
||||
};
|
||||
|
||||
return gulp.src('./dist/**',{cwd:'.'})
|
||||
|
||||
// rename to put in subfolder
|
||||
.pipe(rename(function (path) {
|
||||
path.dirname = pjson.name + '/' + path.dirname;
|
||||
}))
|
||||
|
||||
// gzip, Set Content-Encoding headers and add .gz extension
|
||||
.pipe(awspublish.gzip())
|
||||
|
||||
// publisher will add Content-Length, Content-Type and headers specified above
|
||||
// If not specified it will set x-amz-acl to public-read by default
|
||||
// Noe: this has been made concurrent using concurrent-transform
|
||||
.pipe(concurrent(publisher.publish(headers,{'force':true})), 10)
|
||||
|
||||
// create a cache file to speed up consecutive uploads
|
||||
.pipe(publisher.cache())
|
||||
|
||||
// print upload updates to console
|
||||
.pipe(awspublish.reporter());
|
||||
});
|
||||
|
||||
gulp.task('default', ['webpack']);
|
||||
gulp.task('deploy', ['webpack','s3']);
|
||||
@@ -1,18 +0,0 @@
|
||||
<p class="lead">You discovered the Oscillation of Neutral B Mesons.</p>
|
||||
<h5><b>The Oscillation of Neutral B mesons</b></h5>
|
||||
|
||||
<p>
|
||||
Like neutral Kaons (with which CP violation was discovered for the first time), neutral B mesons can also spontaneously turn into their own antiparticle.
|
||||
Although suspected for a long time, this was first discovered in 1987 by the ARGUS collaboration at DESY in Germany.
|
||||
</p>
|
||||
<p>
|
||||
With neutral B mesons, CP violation can now be studied very effectively.
|
||||
Important experiments making use of B oscillation have been the so-called B factories BaBar (in the US) and Belle (in Japan), as well as LHCb at CERN.
|
||||
These experiments have studied CP violation on a massive scale, looking at a large number of different decays of B mesons, as well as (more recently) Bs mesons and D mesons.
|
||||
So far, no deviation from the CKM mechanism by Kobayashi and Maskawa has been observed.
|
||||
</p>
|
||||
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/B–Bbar_oscillation" target="_blank">B-Bbar on Wikipedia</a></li>
|
||||
</ul>
|
||||
@@ -1,71 +0,0 @@
|
||||
<p class="lead">You discovered CP violation!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>The Mystery of CP Violation</h4>
|
||||
<p>
|
||||
The study of CP violation is concerned with some very fundamental questions:<br>
|
||||
<ul>
|
||||
<li>Are the laws of physics different for matter and antimatter?</li>
|
||||
<li>Why is there an abundance of matter in our universe, instead of equal amounts of matter and antimatter?</li>
|
||||
</ul>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="5">
|
||||
<h4>What is CP?</h4>
|
||||
<p>
|
||||
CP is a possible <em>symmetry</em> of nature.
|
||||
If the laws of nature were symmetric under CP, then matter and antimatter would be governed by the same rules.
|
||||
This means that if we communicated with aliens from a distant galaxy, there would be no way to find out if they are made from matter or antimatter:
|
||||
No experiment they could perform would allow us to deduce if they lived in a matter or antimatter world.
|
||||
On the other hand, if there was a fundamental difference between matter and antimatter, such an experiment would be possible.
|
||||
It turns out that this is the case in our universe!
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="10">
|
||||
<h4>How was CP violation discovered?</h4>
|
||||
<p>
|
||||
In 1964, a team lead by Val Fitch and Jim Cronin performed experiments with <em>neutral Kaons</em>, particles formed by a strange and an anti-down quark.
|
||||
These neutral Kaons have the amazing property that they can spontaneously transform into their own antiparticle.
|
||||
Fitch and Cronin discovered that the rate at which these Kaons changed from matter to antimatter and vice versa was different, clear evidence for CP violation!
|
||||
This discovery came as a total surprise to physicists (it was assumed that nature was symmetric under CP) and earned Cronin and Fitch the <a target="_blank" href="http://www.nobelprize.org/nobel_prizes/physics/laureates/1980/">Nobel price</a> in 1980.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="15">
|
||||
<h4>How is CP violation currently understood?</h4>
|
||||
<p>
|
||||
In 1973, two Japanese physicists, <a target="_blank" href="http://en.wikipedia.org/wiki/Makoto_Kobayashi_(physicist)">Makoto Kobayashi</a> and <a target="_blank" href="http://en.wikipedia.org/wiki/Toshihide_Maskawa">Toshihide Maskawa</a>, found a very simple and elegant way to explain the occurence of CP violation in our universe.
|
||||
The only problem: The explanation required a third generation of quarks (the <em>top</em> and <em>bottom</em> quarks) for which there was zero evidence at the time.
|
||||
</p>
|
||||
<p>
|
||||
This turned out to be an incredible prediction, when both of these quarks were discovered decades later.
|
||||
So far, the idea of Kobayashi and Maskawa, called the <a target="_blank" href="http://en.wikipedia.org/wiki/Cabibbo–Kobayashi–Maskawa_matrix">CKM mechanism</a>, has been able to explain every single occurence of CP violation that physicists managed to detect in the lab.
|
||||
They were awarded the Nobel price in 2008.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="20">
|
||||
<h4>What's next for CP violation?</h4>
|
||||
<p>
|
||||
CP violation is one of the necessary ingredients for explaining the abundance of matter over antimatter in our universe.
|
||||
But there is one problem: The CKM mechanism predicts too little of it.
|
||||
The amount of matter in our universe suggests that a correction or even a complete revolution in our understanding of CP violation is necessary.
|
||||
</p>
|
||||
<p>
|
||||
CP violation remains a hot topic in Physics research.
|
||||
Specialized experiments like the <a href="http://lhcb-public.web.cern.ch/lhcb-public/Welcome.html">LHCb detector</a> at CERN in Switzerland are currently searching for hints of New Physics that could explain how our universe came to be the way it is.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
<section data-min-level="5">
|
||||
<hr>
|
||||
<h5>Resources</h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/CP_violation" target="_blank">Wikipedia on CP violation</a></li>
|
||||
<li data-min-level="10"><a href="http://journals.aps.org/prl/abstract/10.1103/PhysRevLett.13.138" target="_blank">The original publication by Cronin, Fitch et al.</a></li>
|
||||
<li data-min-level="10"><a href="http://en.wikipedia.org/wiki/Kaon#CP_violation_in_neutral_meson_oscillations" target="_blank">Neutral kaon mixing on Wikipedia</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -1,10 +0,0 @@
|
||||
<p class="lead">You discovered the D<sup>*</sup><sub>sJ</sub>(2860)<sup>-</sup> meson.</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<hr>
|
||||
<h5>Resources</h5>
|
||||
<ul>
|
||||
<li><a href="https://indico.cern.ch/event/308116/session/6/contribution/20/material/slides/0.pdf">Original Presentation from the LHCb Experiment</a></li>
|
||||
<li><a href="http://cerncourier.com/cws/article/cern/58193">Article in the CERN Courier</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
<p class="lead">You did it! You discovered the Higgs-boson!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>The Higgs field</h4>
|
||||
<p>
|
||||
The Higgs-Englert field has a central role in our current understanding of the universe.
|
||||
Through a process called <em>Spontaneous Symmetry Breaking</em>, it is responsible for the masses of all massive fundamental particles that we know of.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="5">
|
||||
<h4>What is Spontaneous Symmetry Breaking?</h4>
|
||||
<p>
|
||||
At every point in space, the Higgs field has a certain <em>strength</em>, a number that tells you how active the field is.
|
||||
This is quite similar to temperature: You can assign a temperature to every point in a room, and the temperatures might be different for different points in the room and even change with time.
|
||||
</p>
|
||||
<p>
|
||||
The Higgs-Englert field is the most special fundamental field that we know of: It interacts with nearly all of the other fields (like the electron field or the quark fields).
|
||||
This means that the Higgs field can greatly influence the other fields: If it is active somewhere, then electrons, quarks and other particles in that region will be slowed down by it.
|
||||
This is equivalent to them gaining mass!
|
||||
</p>
|
||||
<p>
|
||||
But if the Higgs field would have an average strength of zero (as is usual for a field), then we would not be able to observe this slowdown (meaning no mass for other particles).
|
||||
</p>
|
||||
<p>
|
||||
So how come this is not the case?
|
||||
It turns out that the Higgs field's <em>potential</em>, which governs how much energy is needed to increase its strength, has a very special form (see below).
|
||||
If the energy density in the universe is low enough, the field will drop down into the valley in the potential.
|
||||
This means it will be <em>locked to a non-zero strength</em>, and other particles gain mass everywhere in the universe!
|
||||
</p>
|
||||
<img src="http://www.quantumdiaries.org/wp-content/uploads/2011/11/Higgs-Potential-lookdown.png" width=550></img>
|
||||
<p style="float:right">
|
||||
Source: <a href="http://www.quantumdiaries.org/2011/11/21/why-do-we-expect-a-higgs-boson-part-i-electroweak-symmetry-breaking/">Flip Tanedo</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="10">
|
||||
<h4>Higgs' contribution</h4>
|
||||
<p>
|
||||
The mechanism of spontaneous symmetry breaking was discovered and explored by various different researchers.
|
||||
But it was Peter Higgs who first proposed, in 1964, that we could find evidence of it by searching for a new fundamental particle, now called the <em>Higgs boson</em>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="15">
|
||||
<h4>Discovery at the LHC</h4>
|
||||
<p>
|
||||
After decades of work, the discovery of the Higgs boson was announced in 2012 by the ATLAS and CMS collaborations at CERN.
|
||||
In 2013, Englert and Higgs received a Nobel Price for their contributions to the Higgs mechanism and the prediction of the Higgs particle.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="20">
|
||||
<h4>The future of Higgs physics</h4>
|
||||
<p>
|
||||
You might think that we now know everything there is to know about the Higgs field, but it turns out that we actually know very little!
|
||||
Questions like
|
||||
<ul>
|
||||
<li>What are the coupling strengths of the Higgs boson to itself?</li>
|
||||
<li>Is there just one Higgs particle or could there more?</li>
|
||||
<li>What is the role of the Higgs field in the early, mysterious <em>inflationary</em> phase of the universe?</li>
|
||||
</ul>
|
||||
are sure to have physicists on the edge of their seats for many years to come!
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Higgs_boson" target="_blank">Higgs boson on Wikipedia</a></li>
|
||||
<li data-min-level="5"><a target="_blank" href="http://www.quantumdiaries.org/2011/11/21/why-do-we-expect-a-higgs-boson-part-i-electroweak-symmetry-breaking/">Quantum Diaries article on Spontaneous Symmetry Breaking</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<p class="lead">You discovered the J/ψ meson!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>The J/ψ meson</h4>
|
||||
<img class="img-responsive" src="assets/info/jpsi.png" alt="A plot from one of the original publications" align="center">
|
||||
<p>
|
||||
The J/ψ is a meson consisting of a charm quark and its antiquark. It is the first excited state of the charmonium (a bound charm-anticharm state), and was discovered independently by two research groups in 1974: one at the Stanford Linear Accelerator Center, led by Burton Richter, and one at the Brookhaven National Laboratory, led by Samuel Ting of MIT. Richter and Ting were awarded the 1976 Nobel Prize in Physics for their shared discovery.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="5">
|
||||
<h5>History of the name</h5>
|
||||
<p>
|
||||
The J/ψ is the only particle with a two-letter name, as a result of its nearly simultaneous discovery by two independent groups. Ting wanted to name the particle “J”, while Richter called it “SP” (after the SPEAR accelerator used at SLAC), a name none of his colleagues liked. Richter finally settled on the Greek letter “ψ” (pronounced “psi”).
|
||||
</p>
|
||||
<p>
|
||||
Since the scientific community considered it unjust to give one of the two discoverers priority, most subsequent publications have referred to the particle as the “J/ψ”.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://prl.aps.org/pdf/PRL/v33/i23/p1404_1" target="_blank">The original presentation of J. J. Aubert et al.</a></li>
|
||||
<li><a href="http://journals.aps.org/prl/pdf/10.1103/PhysRevLett.33.1404" target="_blank">The original presentation of J.-E Augustin et al.</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/J/psi_meson" target="_blank">J/ψ meson on Wikipedia</a></li>
|
||||
</ul>
|
||||
@@ -1,11 +0,0 @@
|
||||
<p class="lead">You discovered the Ξ<sub>b</sub><sup>'-</sup> and the Ξ<sub>b</sub><sup>*-</sup> baryons.</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<hr>
|
||||
<h5>Resources</h5>
|
||||
<ul>
|
||||
<li><a href="http://arxiv.org/abs/1411.4849">The official LHCb publication on ArΧiv</a></li>
|
||||
<li><a href="http://press.web.cern.ch/press-releases/2014/11/lhcb-experiment-observes-two-new-baryon-particles-never-seen">Official CERN press release</a></li>
|
||||
<li><a href="http://physicsworld.com/cws/article/news/2014/nov/25/lhcb-bags-two-new-baryonic-strange-beauty-particles">Article on physicsworld.com</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
<p class="lead">You discovered the bottom quark!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>The bottom (or beauty) quark</h4>
|
||||
<img class="img-responsive" src="assets/info/b.png" alt="A plot from one of the original publications" align="center">
|
||||
<p>
|
||||
The bottom (or beauty) quark is a third-generation quark with a charge of −⅓ times the electron charge.
|
||||
It has a large mass (around 4.2 GeV/c<sup>2</sup> — more that four times the mass of a proton!).
|
||||
The bottom quark is notable because it is a product in almost all decays of the top quark and is a frequent decay product for the Higgs boson.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="5">
|
||||
<h5>History of the discovery</h5>
|
||||
<p>
|
||||
The bottom quark was predicted in 1973 by physicists Makoto Kobayashi and Toshihide Maskawa as part of their explanation for CP violation.
|
||||
The name “bottom” was introduced in 1975 by Haim Harari.
|
||||
The bottom quark was discovered in 1977 by the Fermilab E288 experiment team led by Leon M. Lederman, when collisions produced bottomonia (mesons with a bottom quark and its antiquark).
|
||||
Kobayashi and Maskawa won the 2008 Nobel Prize in Physics for their explanation of CP violation.
|
||||
Upon its discovery, there were efforts to name the bottom quark “beauty”, but “bottom” became the predominant name.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://journals.aps.org/prl/pdf/10.1103/PhysRevLett.39.252" target="_blank">The original presentation of S. W. Herb et al.</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Bottom_quark" target="_blank">The bottom quark on Wikipedia</a></li>
|
||||
</ul>
|
||||
+4
-29
@@ -1,38 +1,13 @@
|
||||
<p class="lead">What are particle detectors?</p>
|
||||
<p class="lead">Cards for science</p>
|
||||
|
||||
<p>
|
||||
Particle detectors can be thought of as high-tech cameras that take “photographs” of phenomena that physicists want to study. These phenomena may originate in nuclear decays, cosmic radiation or interactions in a particle accelerator. Let us take a closer look at detectors such as those used at the LHC, which consist of layers of specialized components each designed to specific particles and identify certain properties.
|
||||
This is a game with a secret rule. You try to put down the next card and work out the rule by trial and error. The rule is randomised each time and there are hints available. At it's base this is a game of inductive reason and the scientific method.
|
||||
</p>
|
||||
|
||||
<h5><b>Components</b></h5>
|
||||
|
||||
<h5><span class="badge" style="background:#FFF371;"> </span> Tracker</h5>
|
||||
<p>
|
||||
The tracker helps us to calculate the momentum of charged particles. They bend due to magnetic field. The smaller the curve radius is, the less momentum the particle had. We also differentiate positive and negative particles based on the direction of the track.
|
||||
Hints:
|
||||
</p>
|
||||
|
||||
<h5><span class="badge" style="background:#C5FF82;"> </span> Electromagnetic calorimeter</h5>
|
||||
<p>
|
||||
The Electromagnetic Calorimeter (ECAL) is used to measure the energies of electrons and photons.
|
||||
This game is based on <a href="http://www.logicmazes.com/games/eleusis/">Eleusis</a> by Robert Abbott and John Golden's <a href="http://www.logicmazes.com/games/eleusis/express.html">Eleusis</a> Express.
|
||||
</p>
|
||||
|
||||
<h5><span class="badge" style="background:#E1FF79;"> </span> Hadronic calorimeter</h5>
|
||||
<p>
|
||||
The Hadron Calorimeter (HCAL) is used to measure the energy of hadrons, composite particles that made of quarks and gluons. Some examples of hadrons are protons, neutrons and pions. It also helps us detect neutrinos but indirectly. Energy needs to be conserved, so if we observe missing enery, this indicates neutrinos or as-yet-undiscovered particles flew through the detector.
|
||||
</p>
|
||||
|
||||
<h5><span class="badge" style="background:#A0B3FF;"> </span> Magnet</h5>
|
||||
<p>
|
||||
Particle detectors require magnets with very strong magnetic fields in order to sufficiently bend particles flying with high momenta. Trajectories of particles with higher momenta bend less, while those with lower momenta bend a lot more. The magnetic field also helps distinguish between positively and negatively charged particles: they bend in opposite directions in the same magnetic field.
|
||||
</p>
|
||||
|
||||
<h5><span class="badge" style="background:#EA301F;"> </span> Muon chamber</h5>
|
||||
<p>
|
||||
Muons are charged particles that are just like electrons and positrons, but are 200 times more massive. Because they can penetrate several metres of iron without interacting, the muon chamber is placed at the very edge of the detector where they are the only particles likely to register a signal.
|
||||
</p>
|
||||
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Particle_detector" target="_blank">Particle detectors on Wikipedia</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Compact_Muon_Solenoid" target="_blank">The CMS detector on Wikipedia</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
<p class="lead">You discovered the strong interaction!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>Quarks and Gluons</h4>
|
||||
<p>
|
||||
For a long time, it was believed that the Proton and the Neutron, which make up the atomic nucleus, were fundamental particles.
|
||||
During the 1950s and 1960, an immense number of new, seemingly fundamental particles was discovered.
|
||||
This "particle zoo" confused physicists greatly, until a radical idea was proposed in 1964:
|
||||
What if these new particles were not fundamental, but instead made up of other particles, called <em>quarks</em>.
|
||||
These quarks would have a new three-fold charge called "color charge" (which has nothing to do with visible colors).
|
||||
Color charge would be transmitted via a new (eight-fold) fundamental particle, called the <em>gluon</em>.
|
||||
</p>
|
||||
<p>
|
||||
Spectacularly, this model could explain all of the newly discovered composite <em>hadrons</em>, and even predict a few that had not been discovered!
|
||||
Shortly afterwards, it was confirmed through experiments with deep inelastic scattering that the Proton and Neutron were not fundamental.
|
||||
They, too, are made up of quarks!
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="1">
|
||||
<hr>
|
||||
<h5>Resources</h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Strong_interaction" target="_blank">Wikipedia on the Strong Interaction</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<p class="lead">You discovered the τ lepton!</p>
|
||||
|
||||
<section data-min-level="1">
|
||||
<h4>The τ lepton</h4>
|
||||
<img class="img-responsive" src="assets/info/tau.png" alt="A plot from the original publication" align="right">
|
||||
<p>
|
||||
The τ (tau) is an elementary particle that can be thought of as a much heavier cousin of the electron, with a spin of ½. It belongs to the family of leptons, along with the electron, the muon, and the three neutrinos. Despite the origin of the word lepton (meaning fine, small, thin) the τ is very massive at 1776.82 MeV/c<sup>2</sup>, which is nearly 3500 times the mass of the electron and around twice the mass of the proton.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section data-min-level="5">
|
||||
<h5>The discovery of the τ</h5>
|
||||
<p>
|
||||
The τ was detected in a series of experiments between 1974 and 1977 by Martin Lewis Perl and his colleagues at the SLAC-LBL group. Their equipment consisted of SLAC’s then-new e<sup>+</sup>e<sup>−</sup> colliding ring, called SPEAR, and the LBL magnetic detector. They could detect and distinguish between leptons, hadrons and photons.
|
||||
</p>
|
||||
<p>
|
||||
Martin Perl shared the 1995 Nobel Prize in Physics with Frederick Reines. The latter was awarded his share of the prize for experimental discovery of the neutrino.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://journals.aps.org/prl/pdf/10.1103/PhysRevLett.35.1489" target="_blank">The original publication by M. L. Perl et al.</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Tau_(particle)" target="_blank">The τ lepton on Wikipedia.</a></li>
|
||||
</ul>
|
||||
@@ -1,17 +0,0 @@
|
||||
<p class="lead">You discovered the top quark!</p>
|
||||
<h5><b>The top quark</b></h5>
|
||||
<img class="img-responsive" src="assets/info/t.png" alt="A proton and an antiproton annhilate to form a top-antitop pair" align="center">
|
||||
|
||||
<p>
|
||||
At 174.2 GeV/c<sup>2</sup>, the top quark is the heaviest particle we know of. It belongs to the third generation of quarks and has a charge of ⅔ times the electron charge. As a result of its large mass, it decays (mostly into bottom quarks) almost instantly after it is produced. This behemoth does not form bound states with other quarks or antiquarks.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It was discovered by the DØ and CDF collaborations at Fermilab in the US.
|
||||
Nowadays, top quarks and their properties are studied intensively by ATLAS and CMS at CERN.
|
||||
</p>
|
||||
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Top_quark" target="_blank">The top quark on Wikipedia</a></li>
|
||||
</ul>
|
||||
@@ -1,19 +0,0 @@
|
||||
<p class="lead">You discovered the W and Z bosons!</p>
|
||||
<h5><b>The weak force</b></h5>
|
||||
<img class="img-responsive" src="assets/info/w.png" alt="A W− boson produced in the transformation of a neutron into a proton" align="center">
|
||||
<p>
|
||||
The weak interaction is a nuclear process that is responsible, among other things, for β (beta) decay the transformation of neutrons into protons. The weak force is mediated by two bosons called the W and the Z. The W comes in two types: W<sup>+</sup> and W</sup>−</sup>. The Z is neutral and is sometimes represented as Z<sup>0</sup>.
|
||||
</p>
|
||||
|
||||
<h5><b>Discovery of the W and Z bosons</b></h5>
|
||||
|
||||
<p>
|
||||
The W and Z bosons are quite massive and so require powerful accelerators in order to be produced and studied. The Super Proton Synchrotron at CERN was the first machine capable of this, and the UA1 collaboration lead by Carlo Rubbia discovered both particles in 1983. Rubbia along with Simon Van der Meer, whose developments on the accelerator allowed such a machine to be built, were jointly awarded the Nobel Prize in Physics in 1984.
|
||||
</p>
|
||||
|
||||
<h5><b>Resources</b></h5>
|
||||
<ul>
|
||||
<li><a href="http://cds.cern.ch/record/854078/" target="_blank">CERN Press Release announcing the discovery of the W boson</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/Weak_interaction" target="_blank">The weak interaction on Wikipedia</a></li>
|
||||
<li><a href="http://en.wikipedia.org/wiki/W_and_Z_bosons" target="_blank">The W and Z bosons on Wikipedia</a></li>
|
||||
</ul>
|
||||
@@ -0,0 +1,41 @@
|
||||
/** App imports **/
|
||||
|
||||
// css
|
||||
require("css/bootstrap.min.css");
|
||||
require("font-awesome/css/font-awesome.css");
|
||||
// require("font-awesome/scss/font-awesome.scss");
|
||||
// require("bower_components/angular-ui-grid/ui-grid.min.css");
|
||||
// require("css/ui-grid.css");
|
||||
require("css/style.css");
|
||||
|
||||
// img
|
||||
require("assets/favicon.png");
|
||||
require("assets/mobile/icon.png");
|
||||
require("assets/mobile/icon.png");
|
||||
require("assets/pc32sw.png");
|
||||
|
||||
// json
|
||||
var jquery = require("jquery");
|
||||
var jqueryUi = require("jquery-ui");
|
||||
var jqueryUiTouchPunch = require("jquery-ui-touch-punch");
|
||||
var jqueryCookie = require("js-cookie");
|
||||
|
||||
var bootstrap = require("bootstrap");
|
||||
// var retina = require("retina");
|
||||
var FastClick = require("fastclick");
|
||||
|
||||
var chai = require("chai");
|
||||
var lodash = require("lodash");
|
||||
|
||||
var angular = require("angular");
|
||||
var angularDragdrop = require("angular-dragdrop");
|
||||
var angularAnimate = require("angular-animate");
|
||||
|
||||
var ObjectStorage = require("js/storage.js");
|
||||
var Helpers = require("js/helpers.js");
|
||||
var Analytics = require("js/analytics.js");
|
||||
var GameObjects = require("js/gameobjects.js");
|
||||
var Rules = require("js/rules.js");
|
||||
var UI = require("js/ui.js");
|
||||
var Game = require("js/game.js");
|
||||
var app = require("js/app.js");
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
/** Custom google analystics events **/
|
||||
var analytics =
|
||||
var Helpers = require("js/helpers");
|
||||
var analytics = module.exports =
|
||||
{
|
||||
enabled: true,
|
||||
|
||||
|
||||
@@ -2,46 +2,44 @@
|
||||
* Define the angular app
|
||||
*/
|
||||
'use strict';
|
||||
var app = (function () {
|
||||
var ObjectStorage = require("js/storage");
|
||||
var Helpers = require("js/helpers");
|
||||
var GameObjects = require("js/gameobjects");
|
||||
var analytics = require("js/analytics");
|
||||
var Game = require("js/game");
|
||||
var Rules = require("js/rules.js");
|
||||
|
||||
var app = (function (Helpers,analytics,Game,Rules) {
|
||||
Helpers.validateSaveVersion();
|
||||
|
||||
var app = angular.module('scienceAlchemy', ['ngDragDrop', 'ui.grid','ngAnimate']);
|
||||
var app = angular.module('scienceAlchemy', ['ngDragDrop','ngAnimate']);
|
||||
|
||||
// directives
|
||||
/**
|
||||
* Provides an easy way to toggle a checkboxes indeterminate property
|
||||
*
|
||||
* @example <input type="checkbox" ui-indeterminate="isUnkown">
|
||||
*/
|
||||
// app.directive('uiIndeterminate', [
|
||||
// function () {
|
||||
//
|
||||
// return {
|
||||
// compile: function (tElm, tAttrs) {
|
||||
// if (!tAttrs.type || tAttrs.type.toLowerCase() !== 'checkbox') {
|
||||
// return angular.noop;
|
||||
// }
|
||||
//
|
||||
// return function ($scope, elm, attrs) {
|
||||
// $scope.$watch(attrs.uiIndeterminate, function (newVal) {
|
||||
// elm[0].indeterminate = !!newVal;
|
||||
// });
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// ]);
|
||||
|
||||
|
||||
/**
|
||||
* Make little score animations when score changes require ng-model="score"
|
||||
* Make little "+2" "-1" score animations when score changes requires ng-model="score"
|
||||
* Associated css:
|
||||
* ```
|
||||
* .update-value { // set constant height, and the position
|
||||
position: relative;
|
||||
right: -2em;
|
||||
top: -1.42857em;
|
||||
height: 1.42857em;
|
||||
}
|
||||
.update-plus { // if the change is +ve
|
||||
color: green;
|
||||
position: relative;
|
||||
}
|
||||
.update-minus {
|
||||
color: red;
|
||||
position: relative;
|
||||
}
|
||||
*/
|
||||
function cfsScoreChange($compile) {
|
||||
return {
|
||||
link: function (scope, element, attrs) {
|
||||
scope.$watch(attrs.ngModel, function (newValue, oldValue) {
|
||||
console.log('value changed, new value is: ' + newValue, oldValue);
|
||||
|
||||
// showUpdateValue
|
||||
var num = newValue-oldValue;
|
||||
var formatted = Helpers.formatNumberPostfix(num);
|
||||
@@ -56,6 +54,7 @@ var app = (function () {
|
||||
.html(formatted);
|
||||
}
|
||||
|
||||
// TODO it would be better to use an ::after element for this
|
||||
// showUpdate
|
||||
element.append(insert);
|
||||
insert.animate({
|
||||
@@ -416,4 +415,5 @@ var app = (function () {
|
||||
|
||||
analytics.init();
|
||||
analytics.sendScreen(analytics.screens.main);
|
||||
})();
|
||||
})(Helpers,analytics,Game,Rules);
|
||||
module.exports=app;
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/** Manages the detector animation in the canvas of the detector pane **/
|
||||
|
||||
var Detector = function(){
|
||||
|
||||
|
||||
return {
|
||||
elements: new GameObjects.Cards(),
|
||||
lastCards: new GameObjects.Cards(),
|
||||
incorrectCards: new GameObjects.Cards(),
|
||||
|
||||
visible: true,
|
||||
|
||||
width: 400,
|
||||
height: 400,
|
||||
|
||||
ratio: 1,
|
||||
|
||||
lastRender: 0,
|
||||
|
||||
bubblr: undefined,
|
||||
|
||||
init: function(game)
|
||||
{
|
||||
// deal first card
|
||||
this.lastCards.push(_.sample(game.elements));
|
||||
},
|
||||
|
||||
/** When a user clicks the detector **/
|
||||
addEvent: function()
|
||||
{
|
||||
// this.bubblr.bubble(); // bubble for 500ms, TODO make one bubble
|
||||
},
|
||||
|
||||
/** When a worker clicks the detector **/
|
||||
addEventExternal: function(numWorkers)
|
||||
{
|
||||
// this.bubblr.genBubbles(numWorkers);
|
||||
},
|
||||
|
||||
/** Draw current events **/
|
||||
draw: function(duration)
|
||||
{
|
||||
// this.bubblr.bubble();
|
||||
},
|
||||
|
||||
|
||||
onDrop: function(event, ui, game){
|
||||
var self=this;
|
||||
console.debug('onDrop',arguments);
|
||||
var $draggable = angular.element(ui.draggable),
|
||||
$droppable = angular.element(event.target);
|
||||
|
||||
// if the dragger came from the elements panels, clone it to here
|
||||
var newElement;
|
||||
if ($draggable.hasClass('element-store')){
|
||||
var elementStore = game.elements.filter(function(e){return e.key==$draggable.data('element');})[0];
|
||||
elementStore.state.amount-=1;
|
||||
newElement = angular.copy(elementStore);
|
||||
this.elements.push(newElement);
|
||||
}
|
||||
|
||||
var observation = game.test
|
||||
console.log('intersectingElements', intersectingElements.length, observation);
|
||||
return observation;
|
||||
},
|
||||
|
||||
/** Run an experiment depending on reactants and conditions **/
|
||||
experiment: function(options,game) {
|
||||
var inputs = options.inputs || [];
|
||||
var inputKeys = inputs.map(function(e){return e.key;});
|
||||
inputKeys.sort(); // this makes reaction be independant of order
|
||||
|
||||
var result = game.testRules(inputKeys);
|
||||
if (result) {
|
||||
this.reaction(inputs,result.reactants,result.results, options.location, game);
|
||||
} else {
|
||||
result = {
|
||||
reactants: [],
|
||||
catalysts: [],
|
||||
conditions: [],
|
||||
results: [],
|
||||
inputs: inputKeys
|
||||
};
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Remove reactants and make results with animations **/
|
||||
reaction: function(inputs,reactants,results,location,game){
|
||||
|
||||
// remove reactants from detector
|
||||
for (var i = 0; i < reactants.length; i++) {
|
||||
// get the uuid from inputs
|
||||
var ingredient = inputs.filter(function(e){return e.key===reactants[i];})[0];
|
||||
var j = _.findIndex(this.elements,{uuid:ingredient.uuid});
|
||||
var removed = this.elements.splice(j,1);
|
||||
}
|
||||
|
||||
// TODO use angular effects to remove in puff of fade
|
||||
|
||||
// add results and discover them
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var resultKey = results[i];
|
||||
|
||||
// make sure it's discovered
|
||||
var elementStore = game.elements.get(resultKey);
|
||||
if (!elementStore.state.discovered){
|
||||
// old discoveries are not interesting
|
||||
game.elements.map(function(e){e.state.interesting=false;});
|
||||
// a new discovery is interesting
|
||||
elementStore.state.interesting=true;
|
||||
elementStore.state.discovered=true;
|
||||
}
|
||||
|
||||
// add new element to beaker
|
||||
var newElem = elementStore.spawn();
|
||||
newElem.state=location;
|
||||
|
||||
this.elements.push(newElem);
|
||||
}
|
||||
|
||||
// effects
|
||||
// this.bubblr.bubble();
|
||||
|
||||
},
|
||||
};
|
||||
};
|
||||
Vendored
-989
@@ -1,989 +0,0 @@
|
||||
/*!!
|
||||
* Canvas 2 Svg v1.0.6
|
||||
* A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Author:
|
||||
* Kerry Liu
|
||||
*
|
||||
* Copyright (c) 2014 Gliffy Inc.
|
||||
*/
|
||||
|
||||
;(function() {
|
||||
"use strict";
|
||||
|
||||
var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities;
|
||||
|
||||
//helper function to format a string
|
||||
function format(str, args) {
|
||||
var keys = Object.keys(args), i;
|
||||
for (i=0; i<keys.length; i++) {
|
||||
str = str.replace(new RegExp("\\{" + keys[i] + "\\}", "gi"), args[keys[i]]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
//helper function that generates a random string
|
||||
function randomString(holder) {
|
||||
var chars, randomstring, i;
|
||||
if (!holder) {
|
||||
throw new Error("cannot create a random attribute name for an undefined object");
|
||||
}
|
||||
chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
|
||||
randomstring = "";
|
||||
do {
|
||||
randomstring = "";
|
||||
for (i = 0; i < 12; i++) {
|
||||
randomstring += chars[Math.floor(Math.random() * chars.length)];
|
||||
}
|
||||
} while (holder[randomstring]);
|
||||
return randomstring;
|
||||
}
|
||||
|
||||
//helper function to map named to numbered entities
|
||||
function createNamedToNumberedLookup(items, radix) {
|
||||
var i, entity, lookup = {}, base10, base16;
|
||||
items = items.split(',');
|
||||
radix = radix || 10;
|
||||
// Map from named to numbered entities.
|
||||
for (i = 0; i < items.length; i += 2) {
|
||||
entity = '&' + items[i + 1] + ';';
|
||||
base10 = parseInt(items[i], radix);
|
||||
lookup[entity] = '&#'+base10+';';
|
||||
}
|
||||
//FF and IE need to create a regex from hex values ie == \xa0
|
||||
lookup["\\xa0"] = ' ';
|
||||
return lookup;
|
||||
}
|
||||
|
||||
//helper function to map canvas-textAlign to svg-textAnchor
|
||||
function getTextAnchor(textAlign) {
|
||||
//TODO: support rtl languages
|
||||
var mapping = {"left":"start", "right":"end", "center":"middle", "start":"start", "end":"end"};
|
||||
return mapping[textAlign] || mapping.start;
|
||||
}
|
||||
|
||||
//helper function to map canvas-textBaseline to svg-dominantBaseline
|
||||
function getDominantBaseline(textBaseline) {
|
||||
//INFO: not supported in all browsers
|
||||
var mapping = {"alphabetic": "alphabetic", "hanging": "hanging", "top":"text-before-edge", "bottom":"text-after-edge", "middle":"central"};
|
||||
return mapping[textBaseline] || mapping.alphabetic;
|
||||
}
|
||||
|
||||
// Unpack entities lookup where the numbers are in radix 32 to reduce the size
|
||||
// entity mapping courtesy of tinymce
|
||||
namedEntities = createNamedToNumberedLookup(
|
||||
'50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
|
||||
'5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
|
||||
'5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
|
||||
'5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
|
||||
'68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
|
||||
'6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
|
||||
'6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
|
||||
'75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
|
||||
'7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
|
||||
'7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
|
||||
'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
|
||||
'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
|
||||
't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
|
||||
'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
|
||||
'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
|
||||
'81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
|
||||
'8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
|
||||
'8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
|
||||
'8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
|
||||
'8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
|
||||
'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
|
||||
'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
|
||||
'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
|
||||
'80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
|
||||
'811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
|
||||
|
||||
|
||||
//Some basic mappings for attributes and default values.
|
||||
STYLES = {
|
||||
"strokeStyle":{
|
||||
svgAttr : "stroke", //corresponding svg attribute
|
||||
canvas : "#000000", //canvas default
|
||||
svg : "none", //svg default
|
||||
apply : "stroke" //apply on stroke() or fill()
|
||||
},
|
||||
"fillStyle":{
|
||||
svgAttr : "fill",
|
||||
canvas : "#000000",
|
||||
svg : null, //svg default is black, but we need to special case this to handle canvas stroke without fill
|
||||
apply : "fill"
|
||||
},
|
||||
"lineCap":{
|
||||
svgAttr : "stroke-linecap",
|
||||
canvas : "butt",
|
||||
svg : "butt",
|
||||
apply : "stroke"
|
||||
},
|
||||
"lineJoin":{
|
||||
svgAttr : "stroke-linejoin",
|
||||
canvas : "miter",
|
||||
svg : "miter",
|
||||
apply : "stroke"
|
||||
},
|
||||
"miterLimit":{
|
||||
svgAttr : "stroke-miterlimit",
|
||||
canvas : 10,
|
||||
svg : 4,
|
||||
apply : "stroke"
|
||||
},
|
||||
"lineWidth":{
|
||||
svgAttr : "stroke-width",
|
||||
canvas : 1,
|
||||
svg : 1,
|
||||
apply : "stroke"
|
||||
},
|
||||
"globalAlpha": {
|
||||
svgAttr : "opacity",
|
||||
canvas : 1,
|
||||
svg : 1,
|
||||
apply : "fill stroke"
|
||||
},
|
||||
"font":{
|
||||
//font converts to multiple svg attributes, there is custom logic for this
|
||||
canvas : "10px sans-serif"
|
||||
},
|
||||
"shadowColor":{
|
||||
canvas : "#000000"
|
||||
},
|
||||
"shadowOffsetX":{
|
||||
canvas : 0
|
||||
},
|
||||
"shadowOffsetY":{
|
||||
canvas : 0
|
||||
},
|
||||
"shadowBlur":{
|
||||
canvas : 0
|
||||
},
|
||||
"textAlign":{
|
||||
canvas : "start"
|
||||
},
|
||||
"textBaseline":{
|
||||
canvas : "alphabetic"
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param gradientNode - reference to the gradient
|
||||
* @constructor
|
||||
*/
|
||||
CanvasGradient = function(gradientNode) {
|
||||
this.__root = gradientNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a color stop to the gradient root
|
||||
*/
|
||||
CanvasGradient.prototype.addColorStop = function(offset, color) {
|
||||
var stop = document.createElementNS("http://www.w3.org/2000/svg", "stop"), regex, matches;
|
||||
stop.setAttribute("offset", offset);
|
||||
if(color.indexOf("rgba") !== -1) {
|
||||
//separate alpha value, since webkit can't handle it
|
||||
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
|
||||
matches = regex.exec(color);
|
||||
stop.setAttribute("stop-color", format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
|
||||
stop.setAttribute("stop-opacity", matches[4]);
|
||||
} else {
|
||||
stop.setAttribute("stop-color", color);
|
||||
}
|
||||
this.__root.appendChild(stop);
|
||||
};
|
||||
|
||||
CanvasPattern = function(pattern, ctx) {
|
||||
this.__root = pattern;
|
||||
this.__ctx = ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* The mock canvas context
|
||||
* @param o - options include:
|
||||
* width - width of your canvas (defaults to 500)
|
||||
* height - height of your canvas (defaults to 500)
|
||||
* enableMirroring - enables canvas mirroring (get image data) (defaults to false)
|
||||
*/
|
||||
ctx = function(o) {
|
||||
|
||||
var defaultOptions = { width:500, height:500, enableMirroring : false }, options;
|
||||
|
||||
//keep support for this way of calling C2S: new C2S(width,height)
|
||||
if(arguments.length > 1) {
|
||||
options = defaultOptions;
|
||||
options.width = arguments[0];
|
||||
options.height = arguments[1];
|
||||
} else if( !o ) {
|
||||
options = defaultOptions;
|
||||
} else {
|
||||
options = o;
|
||||
}
|
||||
|
||||
if(!(this instanceof ctx)) {
|
||||
//did someone call this without new?
|
||||
return new ctx(options);
|
||||
}
|
||||
|
||||
//setup options
|
||||
this.width = options.width || defaultOptions.width;
|
||||
this.height = options.height || defaultOptions.height;
|
||||
this.enableMirroring = options.enableMirroring !== undefined ? options.enableMirroring : defaultOptions.enableMirroring;
|
||||
|
||||
this.canvas = this; ///point back to this instance!
|
||||
this.__canvas = document.createElement("canvas");
|
||||
this.__ctx = this.__canvas.getContext("2d");
|
||||
|
||||
this.__setDefaultStyles();
|
||||
this.__stack = [this.__getStyleState()];
|
||||
this.__groupStack = [];
|
||||
|
||||
//the root svg element
|
||||
this.__root = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
this.__root.setAttribute("version", 1.1);
|
||||
this.__root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
|
||||
this.__root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
|
||||
this.__root.setAttribute("width", this.width);
|
||||
this.__root.setAttribute("height", this.height);
|
||||
|
||||
//make sure we don't generate the same ids in defs
|
||||
this.__ids = {};
|
||||
|
||||
//defs tag
|
||||
this.__defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
||||
this.__root.appendChild(this.__defs);
|
||||
|
||||
//also add a group child. the svg element can't use the transform attribute
|
||||
this.__currentElement = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||
this.__root.appendChild(this.__currentElement);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the specified svg element
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__createElement = function(elementName, properties, resetFill) {
|
||||
var element = document.createElementNS("http://www.w3.org/2000/svg", elementName),
|
||||
keys = Object.keys(properties), i, key;
|
||||
if(resetFill) {
|
||||
//if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
|
||||
element.setAttribute("fill", "none");
|
||||
element.setAttribute("stroke", "none");
|
||||
}
|
||||
for(i=0; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
element.setAttribute(key, properties[key]);
|
||||
}
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies default canvas styles to the context
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__setDefaultStyles = function() {
|
||||
//default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/
|
||||
var keys = Object.keys(STYLES), i, key;
|
||||
for(i=0; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
this[key] = STYLES[key].canvas;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies styles on restore
|
||||
* @param styleState
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__applyStyleState = function(styleState) {
|
||||
var keys = Object.keys(styleState), i, key;
|
||||
for(i=0; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
this[key] = styleState[key];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the current style state
|
||||
* @return {Object}
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__getStyleState = function() {
|
||||
var i, styleState = {}, keys = Object.keys(STYLES), key;
|
||||
for(i=0; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
styleState[key] = this[key];
|
||||
}
|
||||
return styleState;
|
||||
};
|
||||
|
||||
/**
|
||||
* Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke"
|
||||
* @param type
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__applyStyleToCurrentElement = function(type) {
|
||||
var keys = Object.keys(STYLES), i, style, value, id, regex, matches;
|
||||
for(i=0; i<keys.length; i++) {
|
||||
style = STYLES[keys[i]];
|
||||
value = this[keys[i]];
|
||||
if(style.apply) {
|
||||
//is this a gradient or pattern?
|
||||
if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasPattern) {
|
||||
//pattern
|
||||
if(value.__ctx) {
|
||||
//copy over defs
|
||||
while(value.__ctx.__defs.childNodes.length) {
|
||||
id = value.__ctx.__defs.childNodes[0].getAttribute("id");
|
||||
this.__ids[id] = id;
|
||||
this.__defs.appendChild(value.__ctx.__defs.childNodes[0]);
|
||||
}
|
||||
}
|
||||
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
||||
}
|
||||
else if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) {
|
||||
//gradient
|
||||
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
|
||||
} else if(style.apply.indexOf(type)!==-1 && style.svg !== value) {
|
||||
if((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) {
|
||||
//separate alpha value, since illustrator can't handle it
|
||||
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
|
||||
matches = regex.exec(value);
|
||||
this.__currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
|
||||
this.__currentElement.setAttribute(style.svgAttr+"-opacity", matches[4]);
|
||||
} else {
|
||||
//otherwise only update attribute if right type, and not svg default
|
||||
this.__currentElement.setAttribute(style.svgAttr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Will return the closest group or svg node. May return the current element.
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__closestGroupOrSvg = function(node) {
|
||||
node = node || this.__currentElement;
|
||||
if(node.nodeName === "g" || node.nodeName === "svg") {
|
||||
return node;
|
||||
} else {
|
||||
return this.__closestGroupOrSvg(node.parentNode);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the serialized value of the svg so far
|
||||
* @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes.
|
||||
* If true, we attempt to find all named entities and encode it as a numeric entity.
|
||||
* @return serialized svg
|
||||
*/
|
||||
ctx.prototype.getSerializedSvg = function(fixNamedEntities) {
|
||||
var serialized = new XMLSerializer().serializeToString(this.__root),
|
||||
keys, i, key, value, regexp, xmlns;
|
||||
|
||||
//IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
|
||||
xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
|
||||
if(xmlns.test(serialized)) {
|
||||
serialized = serialized.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
|
||||
}
|
||||
|
||||
if(fixNamedEntities) {
|
||||
keys = Object.keys(namedEntities);
|
||||
//loop over each named entity and replace with the proper equivalent.
|
||||
for(i=0; i<keys.length; i++) {
|
||||
key = keys[i];
|
||||
value = namedEntities[key];
|
||||
regexp = new RegExp(key, "gi");
|
||||
if(regexp.test(serialized)) {
|
||||
serialized = serialized.replace(regexp, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serialized;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the root svg
|
||||
* @return
|
||||
*/
|
||||
ctx.prototype.getSvg = function() {
|
||||
return this.__root;
|
||||
};
|
||||
/**
|
||||
* Will generate a group tag.
|
||||
*/
|
||||
ctx.prototype.save = function() {
|
||||
var group = document.createElementNS("http://www.w3.org/2000/svg", "g"), parent = this.__closestGroupOrSvg();
|
||||
this.__groupStack.push(parent);
|
||||
parent.appendChild(group);
|
||||
this.__currentElement = group;
|
||||
this.__stack.push(this.__getStyleState());
|
||||
};
|
||||
/**
|
||||
* Sets current element to parent, or just root if already root
|
||||
*/
|
||||
ctx.prototype.restore = function(){
|
||||
this.__currentElement = this.__groupStack.pop();
|
||||
var state = this.__stack.pop();
|
||||
this.__applyStyleState(state);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to add transform
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__addTransform = function(t) {
|
||||
var transform = this.__currentElement.getAttribute("transform");
|
||||
if(transform) {
|
||||
transform += " ";
|
||||
} else {
|
||||
transform = "";
|
||||
}
|
||||
transform += t;
|
||||
this.__currentElement.setAttribute("transform", transform);
|
||||
};
|
||||
|
||||
/**
|
||||
* scales the current element
|
||||
*/
|
||||
ctx.prototype.scale = function(x, y) {
|
||||
if(y === undefined) {
|
||||
y = x;
|
||||
}
|
||||
this.__addTransform(format("scale({x},{y})", {x:x, y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* rotates the current element
|
||||
*/
|
||||
ctx.prototype.rotate = function(angle){
|
||||
var degrees = (angle * 180 / Math.PI);
|
||||
this.__addTransform(format("rotate({angle},{cx},{cy})", {angle:degrees, cx:0, cy:0}));
|
||||
};
|
||||
|
||||
/**
|
||||
* translates the current element
|
||||
*/
|
||||
ctx.prototype.translate = function(x, y){
|
||||
this.__addTransform(format("translate({x},{y})", {x:x,y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* applies a transform to the current element
|
||||
*/
|
||||
ctx.prototype.transform = function(a, b, c, d, e, f){
|
||||
this.__addTransform(format("matrix({a},{b},{c},{d},{e},{f})", {a:a, b:b, c:c, d:d, e:e, f:f}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new Path Element
|
||||
*/
|
||||
ctx.prototype.beginPath = function(){
|
||||
var path, parent;
|
||||
path = this.__createElement("path", {}, true);
|
||||
parent = this.__closestGroupOrSvg();
|
||||
parent.appendChild(path);
|
||||
this.__currentElement = path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to add path command
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__addPathCommand = function(command){
|
||||
if(this.__currentElement.nodeName === "path") {
|
||||
var d = this.__currentElement.getAttribute("d");
|
||||
if(d) {
|
||||
d += " ";
|
||||
} else {
|
||||
d = "";
|
||||
}
|
||||
d += command;
|
||||
this.__currentElement.setAttribute("d", d);
|
||||
} else {
|
||||
throw new Error("Attempted to add path command to node " + this.__currentElement.nodeName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the move command to the current path element,
|
||||
* if the currentPathElement is not empty create a new path element
|
||||
*/
|
||||
ctx.prototype.moveTo = function(x,y){
|
||||
if(this.__currentElement.nodeName !== "path") {
|
||||
this.beginPath();
|
||||
}
|
||||
this.__addPathCommand(format("M {x} {y}", {x:x, y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes the current path
|
||||
*/
|
||||
ctx.prototype.closePath = function(){
|
||||
this.__addPathCommand("Z");
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a line to command
|
||||
*/
|
||||
ctx.prototype.lineTo = function(x, y){
|
||||
this.__addPathCommand(format("L {x} {y}", {x:x, y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a bezier command
|
||||
*/
|
||||
ctx.prototype.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
|
||||
this.__addPathCommand(format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}",
|
||||
{cp1x:cp1x, cp1y:cp1y, cp2x:cp2x, cp2y:cp2y, x:x, y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a quadratic curve to command
|
||||
*/
|
||||
ctx.prototype.quadraticCurveTo = function(cpx, cpy, x, y){
|
||||
this.__addPathCommand(format("Q {cpx} {cpy} {x} {y}", {cpx:cpx, cpy:cpy, x:x, y:y}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the stroke property on the current element
|
||||
*/
|
||||
ctx.prototype.stroke = function(){
|
||||
this.__applyStyleToCurrentElement("stroke");
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets fill properties on the current element
|
||||
*/
|
||||
ctx.prototype.fill = function(){
|
||||
this.__applyStyleToCurrentElement("fill");
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a rectangle to the path.
|
||||
*/
|
||||
ctx.prototype.rect = function(x, y, width, height){
|
||||
if(this.__currentElement.nodeName !== "path") {
|
||||
this.beginPath();
|
||||
}
|
||||
this.moveTo(x, y);
|
||||
this.lineTo(x+width, y);
|
||||
this.lineTo(x+width, y+height);
|
||||
this.lineTo(x, y+height);
|
||||
this.lineTo(x, y);
|
||||
this.closePath();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* adds a rectangle element
|
||||
*/
|
||||
ctx.prototype.fillRect = function(x, y, width, height){
|
||||
var rect, parent;
|
||||
rect = this.__createElement("rect", {
|
||||
x : x,
|
||||
y : y,
|
||||
width : width,
|
||||
height : height
|
||||
}, true);
|
||||
parent = this.__closestGroupOrSvg();
|
||||
parent.appendChild(rect);
|
||||
this.__currentElement = rect;
|
||||
this.__applyStyleToCurrentElement("fill");
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a rectangle with no fill
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
ctx.prototype.strokeRect = function(x, y, width, height){
|
||||
var rect, parent;
|
||||
rect = this.__createElement("rect", {
|
||||
x : x,
|
||||
y : y,
|
||||
width : width,
|
||||
height : height
|
||||
}, true);
|
||||
parent = this.__closestGroupOrSvg();
|
||||
parent.appendChild(rect);
|
||||
this.__currentElement = rect;
|
||||
this.__applyStyleToCurrentElement("stroke");
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* "Clears" a canvas by just drawing a white rectangle in the current group.
|
||||
*/
|
||||
ctx.prototype.clearRect = function(x, y, width, height) {
|
||||
var rect, parent = this.__closestGroupOrSvg();
|
||||
rect = this.__createElement("rect", {
|
||||
x : x,
|
||||
y : y,
|
||||
width : width,
|
||||
height : height,
|
||||
fill : "#FFFFFF"
|
||||
}, true);
|
||||
parent.appendChild(rect);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a linear gradient to a defs tag.
|
||||
* Returns a canvas gradient object that has a reference to it's parent def
|
||||
*/
|
||||
ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){
|
||||
var grad = this.__createElement("linearGradient", {
|
||||
id : randomString(this.__ids),
|
||||
x1 : x1+"px",
|
||||
x2 : x2+"px",
|
||||
y1 : y1+"px",
|
||||
y2 : y2+"px",
|
||||
"gradientUnits" : "userSpaceOnUse"
|
||||
}, false);
|
||||
this.__defs.appendChild(grad);
|
||||
return new CanvasGradient(grad);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a radial gradient to a defs tag.
|
||||
* Returns a canvas gradient object that has a reference to it's parent def
|
||||
*/
|
||||
ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){
|
||||
var grad = this.__createElement("radialGradient", {
|
||||
id : randomString(this.__ids),
|
||||
cx : x1+"px",
|
||||
cy : y1+"px",
|
||||
r : r1+"px",
|
||||
fx : x0+"px",
|
||||
fy : y0+"px",
|
||||
"gradientUnits" : "userSpaceOnUse"
|
||||
}, false);
|
||||
this.__defs.appendChild(grad);
|
||||
return new CanvasGradient(grad);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the font string and returns svg mapping
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__parseFont = function() {
|
||||
var font = this.font, parts, token, index = 0, data = {
|
||||
style : "normal",
|
||||
size : "10px",
|
||||
family : "sans-serif",
|
||||
weight: "normal",
|
||||
decoration : "none", //underline | none
|
||||
href : null
|
||||
};
|
||||
|
||||
//canvas doesn't support underline natively, but we can pass this attribute
|
||||
if(this.__fontUnderline === "underline") {
|
||||
data.decoration = "underline";
|
||||
}
|
||||
|
||||
//canvas also doesn't support linking, but we can pass this as well
|
||||
if(this.__fontHref) {
|
||||
data.href = this.__fontHref;
|
||||
}
|
||||
|
||||
parts = font.split(" ");
|
||||
token = parts[index];
|
||||
|
||||
//text decoration
|
||||
while(/italic|bold|normal/.test(token)) {
|
||||
if(token === "bold") {
|
||||
data.weight = token; //[normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit]
|
||||
} else {
|
||||
data.style = token; //[normal / italic /oblique /inherit]
|
||||
}
|
||||
//advance to next token
|
||||
index++;
|
||||
token = parts[index];
|
||||
}
|
||||
|
||||
//next token should be font size
|
||||
if(/em|px|pt|%/.test(token)) {
|
||||
data.size = token;
|
||||
index++;
|
||||
}
|
||||
|
||||
//font family?
|
||||
parts.splice(0, index);
|
||||
data.family = parts.join(" ");
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to link text fragments
|
||||
* @param font
|
||||
* @param element
|
||||
* @return {*}
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__wrapTextLink = function(font, element) {
|
||||
if(font.href) {
|
||||
var a = document.createElementNS("http://www.w3.org/2000/svg", "a");
|
||||
a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href);
|
||||
a.appendChild(element);
|
||||
return a;
|
||||
}
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fills or strokes text
|
||||
* @param text
|
||||
* @param x
|
||||
* @param y
|
||||
* @param action - stroke or fill
|
||||
* @private
|
||||
*/
|
||||
ctx.prototype.__applyText = function(text, x, y, action) {
|
||||
var font = this.__parseFont(),
|
||||
parent = this.__closestGroupOrSvg(),
|
||||
textElement = this.__createElement("text", {
|
||||
"font-family" : font.family,
|
||||
"font-size" : font.size,
|
||||
"font-style" : font.style,
|
||||
"font-weight" : font.weight,
|
||||
"text-decoration" : font.decoration,
|
||||
"x" : x,
|
||||
"y" : y,
|
||||
"text-anchor": getTextAnchor(this.textAlign),
|
||||
"dominant-baseline": getDominantBaseline(this.textBaseline)
|
||||
}, true);
|
||||
|
||||
textElement.appendChild(document.createTextNode(text));
|
||||
this.__currentElement = textElement;
|
||||
this.__applyStyleToCurrentElement(action);
|
||||
parent.appendChild(this.__wrapTextLink(font,textElement));
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a text element
|
||||
* @param text
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
ctx.prototype.fillText = function(text, x, y){
|
||||
this.__applyText(text, x, y, "fill");
|
||||
};
|
||||
|
||||
/**
|
||||
* Strokes text
|
||||
* @param text
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
ctx.prototype.strokeText = function(text, x, y){
|
||||
this.__applyText(text, x, y, "stroke");
|
||||
};
|
||||
|
||||
/**
|
||||
* No need to implement this for svg.
|
||||
* @param text
|
||||
* @return {TextMetrics}
|
||||
*/
|
||||
ctx.prototype.measureText = function(text){
|
||||
this.__ctx.font = this.font;
|
||||
return this.__ctx.measureText(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Arc command!
|
||||
*/
|
||||
ctx.prototype.arc = function(x, y, radius, startAngle, endAngle, counterClockwise) {
|
||||
startAngle = startAngle % (2*Math.PI);
|
||||
endAngle = endAngle % (2*Math.PI);
|
||||
if(startAngle === endAngle) {
|
||||
//circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle)
|
||||
endAngle = ((endAngle + (2*Math.PI)) - 0.001 * (counterClockwise ? -1 : 1)) % (2*Math.PI);
|
||||
}
|
||||
var endX = x+radius*Math.cos(endAngle),
|
||||
endY = y+radius*Math.sin(endAngle),
|
||||
startX = x+radius*Math.cos(startAngle),
|
||||
startY = y+radius*Math.sin(startAngle),
|
||||
sweepFlag = counterClockwise ? 0 : 1,
|
||||
largeArcFlag = 0,
|
||||
diff = endAngle - startAngle;
|
||||
|
||||
// https://github.com/gliffy/canvas2svg/issues/4
|
||||
if(diff < 0) {
|
||||
diff += 2*Math.PI;
|
||||
}
|
||||
|
||||
if(counterClockwise) {
|
||||
largeArcFlag = diff > Math.PI ? 0 : 1;
|
||||
} else {
|
||||
largeArcFlag = diff > Math.PI ? 1 : 0;
|
||||
}
|
||||
|
||||
this.moveTo(startX, startY);
|
||||
this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
|
||||
{rx:radius, ry:radius, xAxisRotation:0, largeArcFlag:largeArcFlag, sweepFlag:sweepFlag, endX:endX, endY:endY}));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a ClipPath from the clip command.
|
||||
*/
|
||||
ctx.prototype.clip = function(){
|
||||
var group = this.__closestGroupOrSvg(),
|
||||
clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"),
|
||||
id = randomString(this.__ids),
|
||||
newGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||||
|
||||
group.removeChild(this.__currentElement);
|
||||
clipPath.setAttribute("id", id);
|
||||
clipPath.appendChild(this.__currentElement);
|
||||
|
||||
this.__defs.appendChild(clipPath);
|
||||
|
||||
//set the clip path to this group
|
||||
group.setAttribute("clip-path", format("url(#{id})", {id:id}));
|
||||
|
||||
//clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations
|
||||
// to this path
|
||||
group.appendChild(newGroup);
|
||||
|
||||
this.__currentElement = newGroup;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws a canvas, image or mock context to this canvas.
|
||||
* Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support.
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
|
||||
*/
|
||||
ctx.prototype.drawImage = function(){
|
||||
//convert arguments to a real array
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
image=args[0],
|
||||
dx, dy, dw, dh, sx=0, sy=0, sw, sh, parent, svg, defs, group,
|
||||
currentElement, svgImage, canvas, context, id;
|
||||
|
||||
if(args.length === 3) {
|
||||
dx = args[1];
|
||||
dy = args[2];
|
||||
sw = image.width;
|
||||
sh = image.height;
|
||||
dw = sw;
|
||||
dh = sh;
|
||||
} else if(args.length === 5) {
|
||||
dx = args[1];
|
||||
dy = args[2];
|
||||
dw = args[3];
|
||||
dh = args[4];
|
||||
sw = image.width;
|
||||
sh = image.height;
|
||||
} else if(args.length === 9) {
|
||||
sx = args[1];
|
||||
sy = args[2];
|
||||
sw = args[3];
|
||||
sh = args[4];
|
||||
dx = args[5];
|
||||
dy = args[6];
|
||||
dw = args[7];
|
||||
dh = args[8];
|
||||
} else {
|
||||
throw new Error("Inavlid number of arguments passed to drawImage: " + arguments.length);
|
||||
}
|
||||
|
||||
parent = this.__closestGroupOrSvg();
|
||||
currentElement = this.__currentElement;
|
||||
|
||||
if(image instanceof ctx) {
|
||||
//canvas2svg mock canvas context. In the future we may want to clone nodes instead.
|
||||
//also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context.
|
||||
svg = image.getSvg();
|
||||
defs = svg.childNodes[0];
|
||||
while(defs.childNodes.length) {
|
||||
id = defs.childNodes[0].getAttribute("id");
|
||||
this.__ids[id] = id;
|
||||
this.__defs.appendChild(defs.childNodes[0]);
|
||||
}
|
||||
group = svg.childNodes[1];
|
||||
parent.appendChild(group);
|
||||
this.__currentElement = group;
|
||||
this.translate(dx, dy);
|
||||
this.__currentElement = currentElement;
|
||||
} else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
|
||||
//canvas or image
|
||||
svgImage = document.createElementNS("http://www.w3.org/2000/svg", "image");
|
||||
svgImage.setAttribute("width", dw);
|
||||
svgImage.setAttribute("height", dh);
|
||||
svgImage.setAttribute("preserveAspectRatio", "none");
|
||||
|
||||
if(sx || sy || sw !== image.width || sh !== image.height) {
|
||||
//crop the image using a temporary canvas
|
||||
canvas = document.createElement("canvas");
|
||||
canvas.width = dw;
|
||||
canvas.height = dh;
|
||||
context = canvas.getContext("2d");
|
||||
context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh);
|
||||
image = canvas;
|
||||
}
|
||||
|
||||
svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
|
||||
image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
|
||||
parent.appendChild(svgImage);
|
||||
this.__currentElement = svgImage;
|
||||
this.translate(dx, dy);
|
||||
this.__currentElement = currentElement;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a pattern tag
|
||||
*/
|
||||
ctx.prototype.createPattern = function(image, repetition){
|
||||
var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids),
|
||||
img;
|
||||
pattern.setAttribute("id", id);
|
||||
pattern.setAttribute("width", image.width);
|
||||
pattern.setAttribute("height", image.height);
|
||||
if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
|
||||
img = document.createElementNS("http://www.w3.org/2000/svg", "image");
|
||||
img.setAttribute("width", image.width);
|
||||
img.setAttribute("height", image.height);
|
||||
img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
|
||||
image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
|
||||
pattern.appendChild(img);
|
||||
this.__defs.appendChild(pattern);
|
||||
} else if(image instanceof ctx) {
|
||||
pattern.appendChild(image.__root.childNodes[1]);
|
||||
this.__defs.appendChild(pattern);
|
||||
}
|
||||
return new CanvasPattern(pattern, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Not yet implemented
|
||||
*/
|
||||
ctx.prototype.drawFocusRing = function(){};
|
||||
ctx.prototype.createImageData = function(){};
|
||||
ctx.prototype.getImageData = function(){};
|
||||
ctx.prototype.putImageData = function(){};
|
||||
ctx.prototype.globalCompositeOperation = function(){};
|
||||
ctx.prototype.arcTo = function(){};
|
||||
ctx.prototype.setTransform = function(){};
|
||||
|
||||
//add options for alternative namespace
|
||||
window.C2S = ctx;
|
||||
|
||||
}());
|
||||
Vendored
-196
@@ -1,196 +0,0 @@
|
||||
/*!
|
||||
* Retina.js v1.3.0
|
||||
*
|
||||
* Copyright 2014 Imulus, LLC
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Retina.js is an open source script that makes it easy to serve
|
||||
* high-resolution images to devices with retina displays.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var root = (typeof exports === 'undefined' ? window : exports);
|
||||
var config = {
|
||||
// An option to choose a suffix for 2x images
|
||||
retinaImageSuffix : '@2x',
|
||||
|
||||
// Ensure Content-Type is an image before trying to load @2x image
|
||||
// https://github.com/imulus/retinajs/pull/45)
|
||||
check_mime_type: true,
|
||||
|
||||
// Resize high-resolution images to original image's pixel dimensions
|
||||
// https://github.com/imulus/retinajs/issues/8
|
||||
force_original_dimensions: true
|
||||
};
|
||||
|
||||
function Retina() {}
|
||||
|
||||
root.Retina = Retina;
|
||||
|
||||
Retina.configure = function(options) {
|
||||
if (options === null) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
for (var prop in options) {
|
||||
if (options.hasOwnProperty(prop)) {
|
||||
config[prop] = options[prop];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Retina.init = function(context) {
|
||||
if (context === null) {
|
||||
context = root;
|
||||
}
|
||||
|
||||
var existing_onload = context.onload || function(){};
|
||||
|
||||
context.onload = function() {
|
||||
var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
|
||||
for (i = 0; i < images.length; i += 1) {
|
||||
image = images[i];
|
||||
if (!!!image.getAttributeNode('data-no-retina')) {
|
||||
image.setAttribute('data-at2x-loaded', true);
|
||||
retinaImages.push(new RetinaImage(image));
|
||||
}
|
||||
}
|
||||
existing_onload();
|
||||
};
|
||||
};
|
||||
|
||||
Retina.recheck = function() {
|
||||
var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
|
||||
for (i = 0; i < images.length; i += 1) {
|
||||
image = images[i];
|
||||
if (!!!image.getAttributeNode('data-no-retina')) {
|
||||
if (!!!image.getAttributeNode('data-at2x-loaded')) {
|
||||
image.setAttribute('data-at2x-loaded', true);
|
||||
retinaImages.push(new RetinaImage(image));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Retina.isRetina = function(){
|
||||
var mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';
|
||||
|
||||
if (root.devicePixelRatio > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (root.matchMedia && root.matchMedia(mediaQuery).matches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
var regexMatch = /\.\w+$/;
|
||||
function suffixReplace (match) {
|
||||
return config.retinaImageSuffix + match;
|
||||
}
|
||||
|
||||
function RetinaImagePath(path, at_2x_path) {
|
||||
this.path = path || '';
|
||||
if (typeof at_2x_path !== 'undefined' && at_2x_path !== null) {
|
||||
this.at_2x_path = at_2x_path;
|
||||
this.perform_check = false;
|
||||
} else {
|
||||
if (undefined !== document.createElement) {
|
||||
var locationObject = document.createElement('a');
|
||||
locationObject.href = this.path;
|
||||
locationObject.pathname = locationObject.pathname.replace(regexMatch, suffixReplace);
|
||||
this.at_2x_path = locationObject.href;
|
||||
} else {
|
||||
var parts = this.path.split('?');
|
||||
parts[0] = parts[0].replace(regexMatch, suffixReplace);
|
||||
this.at_2x_path = parts.join('?');
|
||||
}
|
||||
this.perform_check = true;
|
||||
}
|
||||
}
|
||||
|
||||
root.RetinaImagePath = RetinaImagePath;
|
||||
|
||||
RetinaImagePath.confirmed_paths = [];
|
||||
|
||||
RetinaImagePath.prototype.is_external = function() {
|
||||
return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) );
|
||||
};
|
||||
|
||||
RetinaImagePath.prototype.check_2x_variant = function(callback) {
|
||||
var http, that = this;
|
||||
if (this.is_external()) {
|
||||
return callback(false);
|
||||
} else if (!this.perform_check && typeof this.at_2x_path !== 'undefined' && this.at_2x_path !== null) {
|
||||
return callback(true);
|
||||
} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
|
||||
return callback(true);
|
||||
} else {
|
||||
http = new XMLHttpRequest();
|
||||
http.open('HEAD', this.at_2x_path);
|
||||
http.onreadystatechange = function() {
|
||||
if (http.readyState !== 4) {
|
||||
return callback(false);
|
||||
}
|
||||
|
||||
if (http.status >= 200 && http.status <= 399) {
|
||||
if (config.check_mime_type) {
|
||||
var type = http.getResponseHeader('Content-Type');
|
||||
if (type === null || !type.match(/^image/i)) {
|
||||
return callback(false);
|
||||
}
|
||||
}
|
||||
|
||||
RetinaImagePath.confirmed_paths.push(that.at_2x_path);
|
||||
return callback(true);
|
||||
} else {
|
||||
return callback(false);
|
||||
}
|
||||
};
|
||||
http.send();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function RetinaImage(el) {
|
||||
this.el = el;
|
||||
this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
|
||||
var that = this;
|
||||
this.path.check_2x_variant(function(hasVariant) {
|
||||
if (hasVariant) {
|
||||
that.swap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
root.RetinaImage = RetinaImage;
|
||||
|
||||
RetinaImage.prototype.swap = function(path) {
|
||||
if (typeof path === 'undefined') {
|
||||
path = this.path.at_2x_path;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
function load() {
|
||||
if (! that.el.complete) {
|
||||
setTimeout(load, 5);
|
||||
} else {
|
||||
if (config.force_original_dimensions) {
|
||||
that.el.setAttribute('width', that.el.width);
|
||||
that.el.setAttribute('height', that.el.height);
|
||||
}
|
||||
|
||||
that.el.setAttribute('src', path);
|
||||
}
|
||||
}
|
||||
load();
|
||||
};
|
||||
|
||||
|
||||
if (Retina.isRetina()) {
|
||||
Retina.init(root);
|
||||
}
|
||||
})();
|
||||
+6
-2
@@ -1,7 +1,11 @@
|
||||
/**
|
||||
* Game object load/saves game resources and stores game objects
|
||||
*/
|
||||
var Game = (function (Helpers, GameObjects, ObjectStorage) {
|
||||
var ObjectStorage = require("js/storage");
|
||||
var Helpers = require("js/helpers");
|
||||
var GameObjects = require("js/gameobjects");
|
||||
var Rules = require("js/rules.js");
|
||||
var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules) {
|
||||
'use strict';
|
||||
|
||||
var Game = function () {
|
||||
@@ -193,4 +197,4 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
|
||||
};
|
||||
|
||||
return Game;
|
||||
}(Helpers, GameObjects, ObjectStorage));
|
||||
}(Helpers, GameObjects, ObjectStorage,Rules));
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* Game objects such as workers, research, upgrades, and achievements.
|
||||
*/
|
||||
|
||||
var GameObjects = (function () {
|
||||
var GameObjects = module.exports = (function () {
|
||||
'use strict';
|
||||
var GLOBAL_VISIBILITY_THRESHOLD = 0.5;
|
||||
|
||||
|
||||
+4
-2
@@ -1,7 +1,8 @@
|
||||
/** @module Helpers
|
||||
* Define some useful helpers that are used throughout the game.
|
||||
*/
|
||||
var Helpers = (function () {
|
||||
var ObjectStorage = require("js/storage");
|
||||
var Helpers = (function (ObjectStorage) {
|
||||
'use strict';
|
||||
/** Load a file (usually JSON).
|
||||
*/
|
||||
@@ -100,4 +101,5 @@ var Helpers = (function () {
|
||||
validateSaveVersion: validateSaveVersion,
|
||||
analytics: ''
|
||||
};
|
||||
})();
|
||||
})(ObjectStorage);
|
||||
module.exports=Helpers;
|
||||
|
||||
+4
-3
@@ -3,7 +3,8 @@
|
||||
* @param {[type]} function functionName( [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
var Rules = (function functionName(_) {
|
||||
var chai = require("chai");
|
||||
var Rules = module.exports = (function functionName(_,chai) {
|
||||
|
||||
|
||||
|
||||
@@ -250,7 +251,7 @@ var Rules = (function functionName(_) {
|
||||
};
|
||||
|
||||
/** How many combination of this rule **/
|
||||
Rule.prototype.combinations = function (arguments) {
|
||||
Rule.prototype.combinations = function () {
|
||||
var pos = _.map(this.optionDesc, 'possibleVals');
|
||||
var c = 0;
|
||||
for (var i = 0; i < pos.length; i++) {
|
||||
@@ -577,4 +578,4 @@ var Rules = (function functionName(_) {
|
||||
};
|
||||
|
||||
|
||||
})(_);
|
||||
})(_,chai);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/** Allows to save objects to HTML5 local storage.
|
||||
* However, it can only save properties, not functions.
|
||||
*/
|
||||
var ObjectStorage = (function() {
|
||||
var ObjectStorage = module.exports = (function() {
|
||||
'use strict';
|
||||
try {
|
||||
var _s = localStorage;
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
/** Define UI specific stuff.
|
||||
*/
|
||||
var UI = (function () {
|
||||
var FastClick = require("fastclick");
|
||||
var Cookies = require("js-cookie");
|
||||
var UI = module.exports = (function (FastClick,Cookies) {
|
||||
/** Introduce FastClick for faster clicking on mobile.
|
||||
*/
|
||||
$(function() {
|
||||
@@ -84,7 +86,7 @@ var UI = (function () {
|
||||
}
|
||||
|
||||
// display cookie warning
|
||||
if (typeof $.cookie('cookielaw') === 'undefined') {
|
||||
if (typeof Cookies.get('cookielaw') === 'undefined') {
|
||||
var alert = '<div id="cookielaw" class="alert alert-info" role="alert">';
|
||||
alert += '<button type="button" class="btn btn-primary">OK</button>';
|
||||
alert += '<i class="fa fa-info-circle alert-glyph"></i> <span class="alert-text">Particle Clicker uses local storage to store your current progress.</span>';
|
||||
@@ -92,7 +94,7 @@ var UI = (function () {
|
||||
alert = $(alert);
|
||||
alert.find('button').click(function ()
|
||||
{
|
||||
$.cookie('cookielaw', 'informed', { expires: 365 });
|
||||
Cookies.set('cookielaw', 'informed', { expires: 365 });
|
||||
$('#cookielaw').slideUp(300, function() { $('#cookielaw').remove(); });
|
||||
})
|
||||
|
||||
@@ -100,7 +102,7 @@ var UI = (function () {
|
||||
}
|
||||
|
||||
// display new user alert
|
||||
// if (typeof $.cookie('cern60') === 'undefined') {
|
||||
// if (typeof Cookies.get('cern60') === 'undefined') {
|
||||
// var alert = '<div id="cern60" class="alert alert-info" role="alert">';
|
||||
// alert += '<button type="button" class="btn btn-primary">Close</button>';
|
||||
// alert += '<i class="fa fa-area-chart alert-glyph"></i> <span class="alert-text"><a class="alert-link" href="http://home.web.cern.ch/about/updates/2014/12/take-part-cern-60-public-computing-challenge" target="_blank">Join the CERN 60 computing challenge!</a></span>';
|
||||
@@ -108,7 +110,7 @@ var UI = (function () {
|
||||
// alert = $(alert);
|
||||
// alert.find('button').click(function ()
|
||||
// {
|
||||
// $.cookie('cern60', 'closed', { expires: 365 });
|
||||
// Cookies.set('cern60', 'closed', { expires: 365 });
|
||||
// $('#cern60').slideUp(300, function() { $('#cern60').remove(); });
|
||||
// })
|
||||
//
|
||||
@@ -120,41 +122,41 @@ var UI = (function () {
|
||||
showModal: showModal,
|
||||
showLevels: showLevels,
|
||||
showUpdateValue: showUpdateValue
|
||||
}
|
||||
})();
|
||||
};
|
||||
})(FastClick,Cookies);
|
||||
|
||||
|
||||
// I don't know what this is for, so I leave it here for the moment...
|
||||
(function() {
|
||||
var hidden = "hidden";
|
||||
|
||||
// Standards:
|
||||
if (hidden in document)
|
||||
document.addEventListener("visibilitychange", onchange);
|
||||
else if ((hidden = "mozHidden") in document)
|
||||
document.addEventListener("mozvisibilitychange", onchange);
|
||||
else if ((hidden = "webkitHidden") in document)
|
||||
document.addEventListener("webkitvisibilitychange", onchange);
|
||||
else if ((hidden = "msHidden") in document)
|
||||
document.addEventListener("msvisibilitychange", onchange);
|
||||
// IE 9 and lower:
|
||||
else if ('onfocusin' in document)
|
||||
document.onfocusin = document.onfocusout = onchange;
|
||||
// All others:
|
||||
else
|
||||
window.onpageshow = window.onpagehide
|
||||
= window.onfocus = window.onblur = onchange;
|
||||
|
||||
function onchange (evt) {
|
||||
var v = 'visible', h = 'hidden',
|
||||
evtMap = {
|
||||
focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
|
||||
};
|
||||
|
||||
evt = evt || window.event;
|
||||
if (evt.type in evtMap)
|
||||
detector.visible = evtMap[evt.type] == 'visible';
|
||||
else
|
||||
detector.visible = !this[hidden];
|
||||
}
|
||||
})();
|
||||
//
|
||||
// // I don't know what this is for, so I leave it here for the moment...
|
||||
// (function() {
|
||||
// var hidden = "hidden";
|
||||
//
|
||||
// // Standards:
|
||||
// if (hidden in document)
|
||||
// document.addEventListener("visibilitychange", onchange);
|
||||
// else if ((hidden = "mozHidden") in document)
|
||||
// document.addEventListener("mozvisibilitychange", onchange);
|
||||
// else if ((hidden = "webkitHidden") in document)
|
||||
// document.addEventListener("webkitvisibilitychange", onchange);
|
||||
// else if ((hidden = "msHidden") in document)
|
||||
// document.addEventListener("msvisibilitychange", onchange);
|
||||
// // IE 9 and lower:
|
||||
// else if ('onfocusin' in document)
|
||||
// document.onfocusin = document.onfocusout = onchange;
|
||||
// // All others:
|
||||
// else
|
||||
// window.onpageshow = window.onpagehide
|
||||
// = window.onfocus = window.onblur = onchange;
|
||||
//
|
||||
// function onchange (evt) {
|
||||
// var v = 'visible', h = 'hidden',
|
||||
// evtMap = {
|
||||
// focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
|
||||
// };
|
||||
//
|
||||
// evt = evt || window.event;
|
||||
// if (evt.type in evtMap)
|
||||
// detector.visible = evtMap[evt.type] == 'visible';
|
||||
// else
|
||||
// detector.visible = !this[hidden];
|
||||
// }
|
||||
// })();
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
["always makes", "sometimes makes", "never makes", "is", "is made up of","any element","no elements"]
|
||||
@@ -1,145 +0,0 @@
|
||||
[
|
||||
{
|
||||
"key": "research-cpv",
|
||||
"name": "CP violation",
|
||||
"description": "CP symmetry is broken!",
|
||||
"cost_increase": 1.8,
|
||||
"image": "assets/icons/png/CPV.png",
|
||||
"info": "html/CPV.html",
|
||||
"state": {
|
||||
"reputation": 1e0,
|
||||
"cost": 1e1,
|
||||
"info_levels": [ 1, 5, 10, 15, 20 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-jpsi",
|
||||
"name": "J/ψ",
|
||||
"description": "The J/ψ meson consists of a c and an anti-c quark.",
|
||||
"cost_increase": 1.7,
|
||||
"image": "assets/icons/png/Jpsi.png",
|
||||
"info": "html/Jpsi.html",
|
||||
"state": {
|
||||
"reputation": 6e0,
|
||||
"cost": 4e2,
|
||||
"info_levels": [ 1, 5 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-tau",
|
||||
"name": "τ lepton",
|
||||
"description": "The third generation charged lepton.",
|
||||
"cost_increase": 1.6,
|
||||
"image": "assets/icons/png/tau.png",
|
||||
"info": "html/tau.html",
|
||||
"state": {
|
||||
"reputation": 3.3e1,
|
||||
"cost": 1e4,
|
||||
"info_levels": [ 1, 5 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-beauty",
|
||||
"name": "Beauty quark",
|
||||
"description": "The third generation down-type quark.",
|
||||
"cost_increase": 1.5,
|
||||
"image": "assets/icons/png/b.png",
|
||||
"info": "html/b.html",
|
||||
"state": {
|
||||
"reputation": 1.85e2,
|
||||
"cost": 2e5,
|
||||
"info_levels": [ 1, 5 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-gluons",
|
||||
"name": "Gluons",
|
||||
"description": "8 almost identical elementary particles that convey the strong force.",
|
||||
"cost_increase": 1.4,
|
||||
"image": "assets/icons/png/gluons.png",
|
||||
"info": "html/gluons.html",
|
||||
"state": {
|
||||
"reputation": 1e3,
|
||||
"cost": 3e6,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-weak",
|
||||
"name": "W and Z boson",
|
||||
"description": "The carriers of the weak force.",
|
||||
"cost_increase": 1.35,
|
||||
"image": "assets/icons/png/weak.png",
|
||||
"info": "html/weak.html",
|
||||
"state": {
|
||||
"reputation": 5.4e3,
|
||||
"cost": 3.2e7,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-top",
|
||||
"name": "Top quark",
|
||||
"description": "The heaviest of the quarks.",
|
||||
"cost_increase": 1.3,
|
||||
"image": "assets/icons/png/t.png",
|
||||
"info": "html/top.html",
|
||||
"state": {
|
||||
"reputation": 3e4,
|
||||
"cost": 1.28e8,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-boscillations",
|
||||
"name": "B oscillation",
|
||||
"description": "B mesons turn into their antiparticles and vice versa!",
|
||||
"cost_increase": 1.25,
|
||||
"image": "assets/icons/png/BBbar.png",
|
||||
"info": "html/BBbar.html",
|
||||
"state": {
|
||||
"reputation": 1.6e5,
|
||||
"cost": 9e8,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-higgs",
|
||||
"name": "Higgs boson",
|
||||
"description": "It only took us 48 years to find this one!",
|
||||
"cost_increase": 1.2,
|
||||
"image": "assets/icons/png/H.png",
|
||||
"info": "html/H.html",
|
||||
"state": {
|
||||
"reputation": 9e5,
|
||||
"cost": 5e9,
|
||||
"info_levels": [ 1, 5, 10, 15, 20 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-dstars",
|
||||
"name": "D*s⁻",
|
||||
"description": "The first ever observed heavy flavored spin-3 particle.",
|
||||
"cost_increase": 1.15,
|
||||
"image": "assets/icons/png/Dstar_s.png",
|
||||
"info": "html/Dstar_s.html",
|
||||
"state": {
|
||||
"reputation": 4.75e6,
|
||||
"cost": 2.4e10,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "research-xib",
|
||||
"name": "Ξb'- and Ξb*-",
|
||||
"description": "Recently discovered strange beauty baryons. Both differ only in their spin configurations.",
|
||||
"cost_increase": 1.15,
|
||||
"image": "assets/icons/png/Xi_b.png",
|
||||
"info": "html/Xi_b.html",
|
||||
"state": {
|
||||
"reputation": 2.5e7,
|
||||
"cost": 9e10,
|
||||
"info_levels": [ 1 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,750 +0,0 @@
|
||||
[
|
||||
{
|
||||
"key": "upgrade-masterstudents1",
|
||||
"name": "Kinderzimmer",
|
||||
"description": "A shared room for all your Master students. Used to be a server room.",
|
||||
"effect": "Master Students produce +2 data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 4e2,
|
||||
"targets": [{ "key": "workers-masterstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-masterstudents", "property": "hired", "threshold": 5 }],
|
||||
"constant": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-masterstudents2",
|
||||
"name": "Own desk",
|
||||
"description": "Not having to share one is a blessing.",
|
||||
"effect": "Master Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 4e3,
|
||||
"targets": [{ "key": "workers-masterstudents", "property": "rate" }],
|
||||
"requirements": [
|
||||
{ "key": "upgrade-masterstudents1", "property": "used", "threshold": 1 },
|
||||
{ "key": "workers-phdstudents", "property": "hired", "threshold": 1 }
|
||||
],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-masterstudents3",
|
||||
"name": "Grid Access",
|
||||
"description": "Give your Master students access to high performance computing resources.",
|
||||
"effect": "Master Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 4e4,
|
||||
"targets": [{ "key": "workers-masterstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-masterstudents2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-masterstudents4",
|
||||
"name": "Mentoring",
|
||||
"description": "Weekly counseling with a professional physicist.",
|
||||
"effect": "Master Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 4e5,
|
||||
"targets": [{ "key": "workers-masterstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-masterstudents3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-phdstudents1",
|
||||
"name": "Thesis supervision",
|
||||
"description": "Somebody takes care of your PhD Students.",
|
||||
"effect": "PhD Students produce +16 data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e3,
|
||||
"targets": [{ "key": "workers-phdstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-phdstudents", "property": "hired", "threshold": 5 }],
|
||||
"constant": 16
|
||||
},
|
||||
{
|
||||
"key": "upgrade-phdstudents2",
|
||||
"name": "Own office",
|
||||
"description": "Each PhD student gets a quiet place for themselves.",
|
||||
"effect": "PhD Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e4,
|
||||
"targets": [{ "key": "workers-phdstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-phdstudents1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-phdstudents3",
|
||||
"name": "Research Abroad",
|
||||
"description": "1 year of research stay abroad for your PhD students.",
|
||||
"effect": "PhD Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e5,
|
||||
"targets": [{ "key": "workers-phdstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-phdstudents2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-phdstudents4",
|
||||
"name": "Student Assistant",
|
||||
"description": "A personal assistant that takes care of boring tasks.",
|
||||
"effect": "PhD Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e6,
|
||||
"targets": [{ "key": "workers-phdstudents", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-phdstudents3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-postdocs1",
|
||||
"name": "Project Management Seminar",
|
||||
"description": "Hard work also requires soft skills.",
|
||||
"effect": "Postdocs produce +50 data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 7.5e4,
|
||||
"targets": [{ "key": "workers-postdocs", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-postdocs", "property": "hired", "threshold": 5 }],
|
||||
"constant": 50
|
||||
},
|
||||
{
|
||||
"key": "upgrade-postdocs2",
|
||||
"name": "Higher Travel Allowances",
|
||||
"description": "Let your Postdocs go to more conferences.",
|
||||
"effect": "Postdocs produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 7.5e5,
|
||||
"targets": [{ "key": "workers-postdocs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-postdocs1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-postdocs3",
|
||||
"name": "Teaching-free year",
|
||||
"description": "A year without teaching means more productivity.",
|
||||
"effect": "Postdocs produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 7.5e6,
|
||||
"targets": [{ "key": "workers-postdocs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-postdocs2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-postdocs4",
|
||||
"name": "Job security",
|
||||
"description": "You wish...",
|
||||
"effect": "Postdocs produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 7.5e7,
|
||||
"targets": [{ "key": "workers-postdocs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-postdocs3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-fellows1",
|
||||
"name": "Video Meetings",
|
||||
"description": "Participate but also get work done.",
|
||||
"effect": "Fellows produce +4k data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e5,
|
||||
"targets": [{ "key": "workers-fellows", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-fellows", "property": "hired", "threshold": 5 }],
|
||||
"constant": 4e3
|
||||
},
|
||||
{
|
||||
"key": "upgrade-fellows2",
|
||||
"name": "An Extra Year",
|
||||
"description": "Extend your Fellow's contracts.",
|
||||
"effect": "Fellows produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e6,
|
||||
"targets": [{ "key": "workers-fellows", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-fellows1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-fellows3",
|
||||
"name": "External Funding",
|
||||
"description": "Your Fellows are happier and you don't have to pay for it. Excellent!",
|
||||
"effect": "Fellows produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e7,
|
||||
"targets": [{ "key": "workers-fellows", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-fellows2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-fellows4",
|
||||
"name": "Pet Cat",
|
||||
"description": "Makes sure your Fellows go home at one point and eventually get some rest.",
|
||||
"effect": "Fellows produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6e8,
|
||||
"targets": [{ "key": "workers-fellows", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-fellows3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-permanent1",
|
||||
"name": "Daycare",
|
||||
"description": "Someone to take care of your staff's children.",
|
||||
"effect": "Permanent staff produces +20k data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6.5e6,
|
||||
"targets": [{ "key": "workers-permanent", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-permanent", "property": "hired", "threshold": 5 }],
|
||||
"constant": 2e4
|
||||
},
|
||||
{
|
||||
"key": "upgrade-permanent2",
|
||||
"name": "Company Car",
|
||||
"description": "Let your Staff use cars you pay for.",
|
||||
"effect": "Permanent staff produces twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6.5e7,
|
||||
"targets": [{ "key": "workers-permanent", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-permanent1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-permanent3",
|
||||
"name": "Leadership Seminar",
|
||||
"description": "Teach your Permanent Staff some people skills.",
|
||||
"effect": "Permanent staff produces twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6.5e8,
|
||||
"targets": [{ "key": "workers-permanent", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-permanent2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-permanent4",
|
||||
"name": "Office close to the Coffee Machine",
|
||||
"description": "Coffee => Productivity. Simple.",
|
||||
"effect": "Permanent staff produces twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 6.5e9,
|
||||
"targets": [{ "key": "workers-permanent", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-permanent3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-profs1",
|
||||
"name": "More TAs",
|
||||
"description": "Hire extra teaching assistants to take work off your professors' shoulders.",
|
||||
"effect": "Professors produce +300k data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 5e7,
|
||||
"targets": [{ "key": "workers-profs", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-profs", "property": "hired", "threshold": 5 }],
|
||||
"constant": 3e5
|
||||
},
|
||||
{
|
||||
"key": "upgrade-profs2",
|
||||
"name": "Extra Secretary",
|
||||
"description": "Secretaries have to do a lot of work at University. It's good to have them!",
|
||||
"effect": "Professors produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 5e8,
|
||||
"targets": [{ "key": "workers-profs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-profs1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-profs3",
|
||||
"name": "Sabbatical",
|
||||
"description": "Professors take a year off teaching to be more productive.",
|
||||
"effect": "Professors produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 5e9,
|
||||
"targets": [{ "key": "workers-profs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-profs2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-profs4",
|
||||
"name": "Online Courses",
|
||||
"description": "Record once, use often. No more useless time spent in lectures.",
|
||||
"effect": "Professors produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 5e10,
|
||||
"targets": [{ "key": "workers-profs", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-profs3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-nobel1",
|
||||
"name": "Kötbullar",
|
||||
"description": "Delicious Swedish Meatballs that are (probably) served at the Nobel Prize ceremony.",
|
||||
"effect": "Nobel Laureates produce +3M data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 3e8,
|
||||
"targets": [{ "key": "workers-nobel", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-nobel", "property": "hired", "threshold": 5 }],
|
||||
"constant": 3e6
|
||||
},
|
||||
{
|
||||
"key": "upgrade-nobel2",
|
||||
"name": "Street Names",
|
||||
"description": "Name the streets at your facility after Nobel Laureates.",
|
||||
"effect": "Nobel Laureates produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 3e9,
|
||||
"targets": [{ "key": "workers-nobel", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-nobel1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-nobel3",
|
||||
"name": "Summer Vacation",
|
||||
"description": "At this point in their career your Nobel Laureates can afford to take a vacation once in a while.",
|
||||
"effect": "Nobel Laureates produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 3e10,
|
||||
"targets": [{ "key": "workers-nobel", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-nobel2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-nobel4",
|
||||
"name": "Second Nobel Prize",
|
||||
"description": "Only Marie Curie and John Bardeen received such high honours in Physics.",
|
||||
"effect": "Nobel Laureates produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 3e11,
|
||||
"targets": [{ "key": "workers-nobel", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-nobel3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-summies1",
|
||||
"name": "Summer Lectures",
|
||||
"description": "Interesting lectures given by the best in the field.",
|
||||
"effect": "Summmer Students produce +80M data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 2e9,
|
||||
"targets": [{ "key": "workers-summies", "property": "rate" }],
|
||||
"requirements": [{ "key": "workers-summies", "property": "hired", "threshold": 5 }],
|
||||
"constant": 8e7
|
||||
},
|
||||
{
|
||||
"key": "upgrade-summies2",
|
||||
"name": "Poster Sessions",
|
||||
"description": "Have your Summies prepare interesting posters and explain them to their peers.",
|
||||
"effect": "Summer Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 2e10,
|
||||
"targets": [{ "key": "workers-summies", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-summies1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-summies3",
|
||||
"name": "Barbecue",
|
||||
"description": "A nice get-together to increase morale in the group.",
|
||||
"effect": "Summer Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 2e11,
|
||||
"targets": [{ "key": "workers-summies", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-summies2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-summies4",
|
||||
"name": "Pump Hall Parties",
|
||||
"description": "Awesome parties in the CERN pump hall. Sure the hangover does not increase productivity but your morale gets a huge boost.",
|
||||
"effect": "Summer Students produce twice as much data per second.",
|
||||
"icon": "fa-group",
|
||||
"cost": 2e12,
|
||||
"targets": [{ "key": "workers-summies", "property": "rate" }],
|
||||
"requirements": [{ "key": "upgrade-summies3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-coffee",
|
||||
"name": "Free coffee",
|
||||
"description": "Addictively delicious. Also free.",
|
||||
"effect": "All workers produce twice as much data per second.",
|
||||
"icon": "fa-coffee",
|
||||
"cost": 8e10,
|
||||
"targets": [
|
||||
{ "key": "workers-phdstudents", "property": "rate" },
|
||||
{ "key": "workers-postdocs", "property": "rate" },
|
||||
{ "key": "workers-fellows", "property": "rate" },
|
||||
{ "key": "workers-permanent", "property": "rate" },
|
||||
{ "key": "workers-profs", "property": "rate" },
|
||||
{ "key": "workers-nobel", "property": "rate" },
|
||||
{ "key": "workers-summies", "property": "rate" }
|
||||
],
|
||||
"requirements": [
|
||||
{ "key": "workers-phdstudents", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-postdocs", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-fellows", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-permanent", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-profs", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-nobel", "property": "hired", "threshold": 1 },
|
||||
{ "key": "workers-summies", "property": "hired", "threshold": 1 }
|
||||
],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy1",
|
||||
"name": "√s = 1.4 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e2,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy2",
|
||||
"name": "√s = 28 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e3,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy1", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy3",
|
||||
"name": "√s = 45 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e4,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy2", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy4",
|
||||
"name": "√s = 209 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e5,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy3", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy5",
|
||||
"name": "√s = 450 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e6,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy4", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy6",
|
||||
"name": "√s = 800 GeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e7,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy5", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy7",
|
||||
"name": "√s = 1 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e8,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy6", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy8",
|
||||
"name": "√s = 3.5 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e9,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy7", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy9",
|
||||
"name": "√s = 6 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e10,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy8", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy10",
|
||||
"name": "√s = 8 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e11,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy9", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy11",
|
||||
"name": "√s = 13 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e12,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy10", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-energy12",
|
||||
"name": "√s = 14 TeV",
|
||||
"description": "Increased centre-of-mass energy.",
|
||||
"effect": "Double the amount of data per click.",
|
||||
"icon": "fa-bolt",
|
||||
"cost": 2e13,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy11", "property": "used", "threshold": 1 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi1",
|
||||
"name": "L = 1×10³⁰ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+3 data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e2,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [],
|
||||
"constant": 3
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi2",
|
||||
"name": "L = 2×10³⁰ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+15 data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e3,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy1", "property": "used", "threshold": 1 }],
|
||||
"constant": 15
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi3",
|
||||
"name": "L = 4×10³⁰ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+75 data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e4,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy2", "property": "used", "threshold": 1 }],
|
||||
"constant": 75
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi4",
|
||||
"name": "L = 6×10³⁰ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+375 data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e5,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy3", "property": "used", "threshold": 1 }],
|
||||
"constant": 375
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi5",
|
||||
"name": "L = 1×10³¹ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+1875 data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e6,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy4", "property": "used", "threshold": 1 }],
|
||||
"constant": 1875
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi6",
|
||||
"name": "L = 2×10³¹ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+9.4k data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e7,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy5", "property": "used", "threshold": 1 }],
|
||||
"constant": 9400
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi7",
|
||||
"name": "L = 4×10³¹ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+47k data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e8,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy6", "property": "used", "threshold": 1 }],
|
||||
"constant": 47000
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi8",
|
||||
"name": "L = 8×10³¹ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+235k data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e9,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy7", "property": "used", "threshold": 1 }],
|
||||
"constant": 235e3
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi9",
|
||||
"name": "L = 1×10³² cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+1.2M data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e10,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy8", "property": "used", "threshold": 1 }],
|
||||
"constant": 1.2e6
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi10",
|
||||
"name": "L = 4×10³² cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+6M data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e11,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy9", "property": "used", "threshold": 1 }],
|
||||
"constant": 6e6
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi11",
|
||||
"name": "L = 6×10³³ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+30M data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e12,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy10", "property": "used", "threshold": 1 }],
|
||||
"constant": 3e7
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lumi12",
|
||||
"name": "L = 1×10³⁴ cm⁻²s⁻¹",
|
||||
"description": "Increased instantaneous luminosity.",
|
||||
"effect": "+150M data per click.",
|
||||
"icon": "fa-bullseye",
|
||||
"cost": 8e13,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [{ "key": "upgrade-energy11", "property": "used", "threshold": 1 }],
|
||||
"constant": 1.5e8
|
||||
},
|
||||
{
|
||||
"key": "upgrade-sps",
|
||||
"name": "Super Proton Synchrotron",
|
||||
"description": "A larger particle smasher.",
|
||||
"effect": "Ten times the amount of data per click.",
|
||||
"icon": "fa-circle-o-notch",
|
||||
"cost": 5e5,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [
|
||||
{ "key": "upgrade-energy3", "property": "used", "threshold": 1 },
|
||||
{ "key": "upgrade-lumi3", "property": "used", "threshold": 1 }
|
||||
],
|
||||
"factor": 10
|
||||
},
|
||||
{
|
||||
"key": "upgrade-tevatron",
|
||||
"name": "Tevatron",
|
||||
"description": "A larger particle smasher.",
|
||||
"effect": "Ten times the amount of data per click.",
|
||||
"icon": "fa-circle-o-notch",
|
||||
"cost": 5e7,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [
|
||||
{ "key": "upgrade-energy6", "property": "used", "threshold": 1 },
|
||||
{ "key": "upgrade-lumi6", "property": "used", "threshold": 1 }
|
||||
],
|
||||
"factor": 10
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lhc",
|
||||
"name": "Large Hadron Collider",
|
||||
"description": "A larger particle smasher.",
|
||||
"effect": "Ten times the amount of data per click.",
|
||||
"icon": "fa-circle-o-notch",
|
||||
"cost": 5e10,
|
||||
"targets": [{ "key": "lab", "property": "detector" }],
|
||||
"requirements": [
|
||||
{ "key": "upgrade-energy9", "property": "used", "threshold": 1 },
|
||||
{ "key": "upgrade-lumi9", "property": "used", "threshold": 1 }
|
||||
],
|
||||
"factor": 10
|
||||
},
|
||||
{
|
||||
"key": "upgrade-cpv1",
|
||||
"name": "B factories",
|
||||
"description": "",
|
||||
"effect": "Future CP violation research gives double the amount of reputation.",
|
||||
"icon": "fa-newspaper-o",
|
||||
"cost": 7500,
|
||||
"targets": [{ "key": "research-cpv", "property": "reputation" }],
|
||||
"requirements": [{ "key": "research-cpv", "property": "level", "threshold": 5 }],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-inspire",
|
||||
"name": "Inspire HEP",
|
||||
"description": "Publish your research online.",
|
||||
"effect": "Double the reputation for all future research.",
|
||||
"icon": "fa-newspaper-o",
|
||||
"cost": 1e12,
|
||||
"targets": [
|
||||
{ "key": "research-cpv", "property": "reputation" },
|
||||
{ "key": "research-jpsi", "property": "reputation" },
|
||||
{ "key": "research-tau", "property": "reputation" },
|
||||
{ "key": "research-beauty", "property": "reputation" },
|
||||
{ "key": "research-gluons", "property": "reputation" },
|
||||
{ "key": "research-weak", "property": "reputation" },
|
||||
{ "key": "research-top", "property": "reputation" },
|
||||
{ "key": "research-boscillations", "property": "reputation" },
|
||||
{ "key": "research-higgs", "property": "reputation" },
|
||||
{ "key": "research-dstars", "property": "reputation" },
|
||||
{ "key": "research-xib", "property": "reputation" }
|
||||
],
|
||||
"requirements": [
|
||||
{ "key": "research-cpv", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-jpsi", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-tau", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-beauty", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-gluons", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-weak", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-top", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-boscillations", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-higgs", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-dstars", "property": "level", "threshold": 1 },
|
||||
{ "key": "research-xib", "property": "level", "threshold": 1 }
|
||||
],
|
||||
"factor": 2
|
||||
},
|
||||
{
|
||||
"key": "upgrade-lhcb",
|
||||
"name": "LHCb",
|
||||
"description": "CP violation research on a whole new level.",
|
||||
"effect": "Future research of CP violation gives +1M reputation.",
|
||||
"icon": "fa-",
|
||||
"cost": 4e11,
|
||||
"targets": [{"key": "research-cpv", "property": "reputation"}],
|
||||
"requirements": [
|
||||
{ "key": "research-cpv", "property": "level", "threshold": 15 },
|
||||
{ "key": "upgrade-lhc", "property": "used", "threshold": 1 }
|
||||
],
|
||||
"constant": 1e6
|
||||
}
|
||||
]
|
||||
@@ -1,82 +0,0 @@
|
||||
[
|
||||
{
|
||||
"key": "workers-masterstudents",
|
||||
"name": "Master Students",
|
||||
"description": "Cheap and enthusiastic workforce, they can save you a lot of work.",
|
||||
"cost_increase": 1.5,
|
||||
"state": {
|
||||
"cost": 4e1,
|
||||
"rate": 1e0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-phdstudents",
|
||||
"name": "PhD Students",
|
||||
"description": "They decided to do a PhD. Now they are working hard.",
|
||||
"cost_increase": 1.45,
|
||||
"state": {
|
||||
"cost": 6e2,
|
||||
"rate": 8e0
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-postdocs",
|
||||
"name": "Postdocs",
|
||||
"description": "These brilliant minds are here only to serve your needs.",
|
||||
"cost_increase": 1.4,
|
||||
"state": {
|
||||
"cost": 7.5e3,
|
||||
"rate": 2.5e1
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-fellows",
|
||||
"name": "Research Fellows",
|
||||
"description": "You pay them a lot. They work a lot.",
|
||||
"cost_increase": 1.35,
|
||||
"state": {
|
||||
"cost": 8e4,
|
||||
"rate": 1e2
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-permanent",
|
||||
"name": "Permanent Staff",
|
||||
"description": "Somebody who gets a permanent position in physics has to be good.",
|
||||
"cost_increase": 1.3,
|
||||
"state": {
|
||||
"cost": 7e5,
|
||||
"rate": 9e3
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-profs",
|
||||
"name": "Tenured Professors",
|
||||
"description": "They bring their own group along and are able to get a lot of work done.",
|
||||
"cost_increase": 1.25,
|
||||
"state": {
|
||||
"cost": 5e6,
|
||||
"rate": 1.2e5
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-nobel",
|
||||
"name": "Nobel Laureates",
|
||||
"description": "They received their prize for a reason.",
|
||||
"cost_increase": 1.2,
|
||||
"state": {
|
||||
"cost": 3e7,
|
||||
"rate": 1.5e6
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "workers-summies",
|
||||
"name": "Summer Students",
|
||||
"description": "Their best ideas come between two parties.",
|
||||
"cost_increase": 1.15,
|
||||
"state": {
|
||||
"cost": 1.25e8,
|
||||
"rate": 2e7
|
||||
}
|
||||
}
|
||||
]
|
||||
+46
-5
@@ -2,40 +2,81 @@
|
||||
"name": "sciencealchemy",
|
||||
"version": "0.0.5",
|
||||
"description": "Science Alchemy",
|
||||
"main": "js/app.js",
|
||||
"keywords": [
|
||||
"cards",
|
||||
"inductive",
|
||||
"game",
|
||||
"science",
|
||||
"eleusis"
|
||||
],
|
||||
"main": "index.js",
|
||||
"repository": "https://gitlab.com/wassname/sciencealchemy",
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "bower install",
|
||||
"prestart": "npm install",
|
||||
"start": "http-server -a 0.0.0.0 -p 8000",
|
||||
"dev": "webpack-dev-server -d",
|
||||
"start": "webpack-dev-server",
|
||||
"prod": "NODE_ENV=production & webpack-dev-server",
|
||||
"pretest": "npm install",
|
||||
"test": "node node_modules/karma/bin/karma start test/karma.conf.js",
|
||||
"test-single-run": "node node_modules/karma/bin/karma start test/karma.conf.js --single-run",
|
||||
"build": "webpack",
|
||||
"preupdate-webdriver": "npm install",
|
||||
"update-webdriver": "webdriver-manager update",
|
||||
"preprotractor": "npm run update-webdriver",
|
||||
"protractor": "protractor test/protractor-conf.js",
|
||||
"update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('bower_components/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'app/index-async.html');\""
|
||||
"protractor": "protractor test/protractor-conf.js"
|
||||
},
|
||||
"author": "wassname",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"angular": "^1.4.9",
|
||||
"angular-animate": "^1.5.0",
|
||||
"angular-dragdrop": "^1.0.13",
|
||||
"bootstrap": "^3.3.6",
|
||||
"chai": "^3.5.0",
|
||||
"fastclick": "^1.0.6",
|
||||
"font-awesome": "^4.5.0",
|
||||
"jquery": "2.1.4",
|
||||
"jquery-ui": "^1.10.5",
|
||||
"jquery-ui-touch-punch": "^0.2.3",
|
||||
"js-cookie": "^2.1.0",
|
||||
"lodash": "^4.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.3.3",
|
||||
"babel-core": "^6.5.2",
|
||||
"babel-loader": "^6.2.4",
|
||||
"bower": "^1.7.7",
|
||||
"colors": "^1.1.2",
|
||||
"css-loader": "^0.23.1",
|
||||
"csswring": "^4.2.1",
|
||||
"eslint": "^2.2.0",
|
||||
"eslint-config-angular": "^0.4.0",
|
||||
"eslint-plugin-angular": "^0.15.0",
|
||||
"exports-loader": "^0.6.3",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"gulp-awspublish": "^3.0.1",
|
||||
"html-webpack-plugin": "^2.9.0",
|
||||
"http-server": "^0.9.0",
|
||||
"imports-loader": "^0.6.5",
|
||||
"jasmine": "^2.4.1",
|
||||
"karma": "^0.13.21",
|
||||
"karma-chrome-launcher": "^0.2.2",
|
||||
"karma-firefox-launcher": "^0.1.7",
|
||||
"karma-jasmine": "^0.3.7",
|
||||
"ng-html2js": "^2.0.0",
|
||||
"path": "^0.12.7",
|
||||
"protractor": "^3.1.1",
|
||||
"sass-loader": "^3.1.2",
|
||||
"shelljs": "^0.6.0",
|
||||
"style-loader": "^0.13.0",
|
||||
"tmp": "0.0.28",
|
||||
"webdriver": "0.0.1"
|
||||
"url-loader": "^0.5.7",
|
||||
"webdriver": "0.0.1",
|
||||
"webpack": "^1.12.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
'use strict';
|
||||
var path = require('path');
|
||||
var colors = require('colors');
|
||||
var webpack = require('webpack');
|
||||
var WebpackDevServer = require("webpack-dev-server");
|
||||
|
||||
// loaders
|
||||
var fileLoader = require("file-loader");
|
||||
var importsLoader = require("imports-loader");
|
||||
var urlload = require("url-loader");
|
||||
|
||||
// css loaders
|
||||
var cssLoader = require("css-loader");
|
||||
var styleLoader = require("style-loader");
|
||||
var autoprefixer = require('autoprefixer');
|
||||
var csswring = require('csswring');
|
||||
|
||||
// text
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
|
||||
/* debug for build folder, not debug for uglify into dist folder */
|
||||
var DEBUG = (process.env.NODE_ENV !== 'production');
|
||||
var DIR = DEBUG ? 'build':'dist';
|
||||
console.log('Running in DEBUG='+DEBUG+' mode');
|
||||
|
||||
/* Provide globals to any who mention them */
|
||||
var provide = new webpack.ProvidePlugin({
|
||||
"log": "loglevel",
|
||||
"_": "lodash",
|
||||
"jQuery": "jquery",
|
||||
"jquery": "jquery",
|
||||
"$": "jquery",
|
||||
"window.jQuery": "jquery",
|
||||
});
|
||||
// extract css file into styles.css
|
||||
var extractText = new ExtractTextPlugin("[name].css", {
|
||||
allChunks: true
|
||||
});
|
||||
// multiple extract instances
|
||||
var extractLESS = new ExtractTextPlugin('[name].less');
|
||||
//
|
||||
// inject bundles into html file template. Note html loader can overwrite output
|
||||
var htmlWebpack = new HtmlWebpackPlugin({
|
||||
template: 'webpack.html',
|
||||
inject: 'body',
|
||||
filename: 'index.html', // otherwise this overrides the template, wierd
|
||||
hash: true,
|
||||
showErrors: DEBUG // this will override template
|
||||
});
|
||||
// uglify in production
|
||||
var uglifyJsPlugin = new webpack.optimize.UglifyJsPlugin({
|
||||
minimize: !DEBUG,
|
||||
sourceMap: DEBUG,
|
||||
mangle: !DEBUG,
|
||||
dropDebugger: true,
|
||||
dropConsole: true,
|
||||
});
|
||||
|
||||
var plugins = [
|
||||
provide,
|
||||
extractText,
|
||||
new webpack.optimize.OccurenceOrderPlugin(true),
|
||||
htmlWebpack,
|
||||
];
|
||||
if (DEBUG){
|
||||
// DEVELOPMENT
|
||||
//plugins.push(
|
||||
// new webpack.HotModuleReplacementPlugin()
|
||||
//);
|
||||
} else {
|
||||
plugins.push(
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
uglifyJsPlugin
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
target: "web",
|
||||
entry: {
|
||||
clientApp: 'index.js',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, DIR),
|
||||
//publicPath: '/' + DIR + '/',
|
||||
filename: '[name].bundle.js',
|
||||
libraryTarget:'umd', //var [CommonJs, AMD, umd,this]
|
||||
library: '[name]' // If set, export the bundle as library
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{test: /\.js?$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|bower_components)/ },
|
||||
{test: /\.jsx?$/, loader: 'babel-loader?cacheDirectory', exclude: /(node_modules|bower_components)/ },
|
||||
{ test: /\.(jpe?g|png|gif)$/i, loader: "file?name=[path][name].[ext]" },
|
||||
{ test: /\.(mp3|ac3|ogg|m4a|wav)$/i, loader: "file?name=[path][name].[ext]" },
|
||||
{ test: /\.(ttf|woff|eot|svg|woff2)(\?.*$|$)/i, loader: "file?name=[path][name].[ext]" },
|
||||
{ test: /\.(json)$/i, loader: "file?name=[path][name].[ext]" },
|
||||
// { test: /\.html/, loader: 'file?name=[path][name].[ext]'}, // breaks html template
|
||||
{ test: /\.(less)$/i, loader: extractLESS.extract("style-loader", "css-loader",'less-loader') },
|
||||
{ test: /\.(css)$/i, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
root: [
|
||||
// paths to look in
|
||||
path.resolve(__dirname),
|
||||
path.resolve('./js/external'),
|
||||
path.resolve('./js'),
|
||||
path.resolve('./css'),
|
||||
path.resolve('./json')
|
||||
],
|
||||
alias: {
|
||||
// "phaser-arcade-physics": "phaser/build/custom/phaser-arcade-physics.js",
|
||||
// jquery: "jquery/src/jquery"
|
||||
},
|
||||
// extentions to auto add if needed
|
||||
extensions: ["", ".js"]
|
||||
},
|
||||
postcss: [autoprefixer, csswring],
|
||||
debug: DEBUG, // Switch loaders to debug mode.
|
||||
// Create Sourcemaps for the bundle
|
||||
devtool: DEBUG ? 'source-map' : false, // slower than 'cheap-module-eval-source-map'
|
||||
plugins: plugins
|
||||
};
|
||||
+17
-87
@@ -7,15 +7,9 @@
|
||||
|
||||
<meta property="og:title" content="Science Alchemy">
|
||||
<meta property="og:type" content="game">
|
||||
<meta property="og:description" content="An addictive incremental game that was made during the CERN Webfest 2014. It takes the player on a historic journey through modern particle physics.">
|
||||
<meta property="og:image" content="https://avatars2.githubusercontent.com/u/8345868">
|
||||
<meta property="og:description" content="A card game where you work out the secret rule to determine which cards can be played next.">
|
||||
<meta property="og:image" content="assets/favicon.png">
|
||||
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.css">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="bower_components/angular-ui-grid/ui-grid.min.css">
|
||||
<link rel="stylesheet" href="css/ui-grid.css">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
|
||||
<link rel="icon" type="image/png" href="assets/favicon.png" />
|
||||
<link rel="apple-touch-icon" href="assets/mobile/icon.png">
|
||||
@@ -25,6 +19,7 @@
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div style="display:none">A card game where you work out the secret rule to determine which cards can be played next.</div>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
@@ -48,18 +43,7 @@
|
||||
<li><a href="#" ng-click="restart()"><i class="fa fa-refresh"></i> Restart</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<!--<li><a href="#" data-toggle="modal" data-target="#myModal"><i class="fa fa-users"></i> About</a></li>-->
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="https://github.com/particle-clicker/particle-clicker/" target="_blank"><i class="fa fa-github"></i> GitHub</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-share-alt"></i> Social<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://facebook.com/particleclicker"><i class="fa fa-facebook-square"></i> Facebook</a></li>
|
||||
<li><a href="https://twitter.com/particleclicker"><i class="fa fa-twitter"></i> Twitter</a></li>
|
||||
<li><a href="https://plus.google.com/share?url=http%3A%2F%2Fcern.ch%2Fparticle-clicker" target="_blank" title="Share on Google+"><i class="fa fa-google-plus-square"></i> Google+</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#" data-toggle="modal" data-target="#myModal"><i class="fa fa-users"></i> About</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,7 +89,6 @@
|
||||
|
||||
<div id="column-lab" class="col-xs-6 col-md-6 col-md-6s col-lg-7 col-no-padding-xs" ng-controller="LabController as lc">
|
||||
|
||||
<!-- <input class="hidden-xs" id="labname" value="{{ lc.lab.state.name }}" ng-model="lc.lab.state.name" ng-cloak> -->
|
||||
<div class="row status" ng-cloak>
|
||||
<div class="col-xs-12 text-center col-no-padding-xs">
|
||||
|
||||
@@ -195,24 +178,6 @@
|
||||
</div>
|
||||
<button id="detector-info" type="button" class="btn btn-info" ng-click="lc.showDetectorInfo()"><i class="fa fa-info"></i></button>
|
||||
|
||||
<!-- <div class="row status" ng-cloak>
|
||||
<div class="col-xs-4 text-center col-no-padding-xs">
|
||||
<strong>Score</strong><br>
|
||||
{{ lc.lab.state.score | niceNumber }}
|
||||
<div class="update-value" id="update-data"></div>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center col-no-padding-xs">
|
||||
<strong>Rank</strong><br>
|
||||
{{ lc.lab.state.rank | niceNumber }}
|
||||
<div class="update-value" id="update-reputation"></div>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center col-no-padding-xs">
|
||||
<strong>High Score</strong><br>
|
||||
{{ lc.lab.state.highScore | niceNumber }}
|
||||
<div class="update-value" id="update-funding"></div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 col-md-3s col-lg-2 col-no-padding visible-md-block visible-lg-block">
|
||||
@@ -224,6 +189,8 @@
|
||||
</div>
|
||||
<div class="panel-body scrollable large" id="upgradesLarge">
|
||||
<div id="upgradesContent" class="left-list" ng-controller="UpgradesController as uc">
|
||||
|
||||
<!-- A more complicated hypothesis display... too complicated I guess -->
|
||||
<!-- <label>Search: <input ng-model="searchText"></label> -->
|
||||
<!-- <ul class="form-inline hypotheses" ng-cloak>
|
||||
<li ng-repeat="rule in uc.rules|filter:searchText">
|
||||
@@ -280,7 +247,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="achievements-modal" tabindex="-1" role="dialog" aria-labelledby="achievements-label" aria-hidden="true" ng-controller="AchievementsController">
|
||||
<!-- <div class="modal fade" id="achievements-modal" tabindex="-1" role="dialog" aria-labelledby="achievements-label" aria-hidden="true" ng-controller="AchievementsController">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -299,9 +266,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="modal fade" id="stats-modal" tabindex="-1" role="dialog" aria-labelledby="stats-label" aria-hidden="true" ng-controller="StatsController">
|
||||
<!-- <div class="modal fade" id="stats-modal" tabindex="-1" role="dialog" aria-labelledby="stats-label" aria-hidden="true" ng-controller="StatsController">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -317,7 +284,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div id="achievements-container" class="col-xs-6 col-sm-3"></div>
|
||||
<div id="messages-container" class="col-xs-6 col-sm-3"></div>
|
||||
@@ -337,50 +304,21 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h4>About</h4>
|
||||
<p class="small">Version: 0.9</p>
|
||||
<p class="small bg-warning">This is a pre-release. If you encounter any bugs please report them using <a href="https://github.com/particle-clicker/particle-clicker/issues"><i class="fa fa-github"></i> GitHub issues</a>. This game runs best in landscape mode. Performance of the event display may rely heavily on your hardware.</p>
|
||||
<p>Science Alchemy is a game that was made during the <a href="https://webfest.web.cern.ch">CERN Webfest 2014</a>. The idea is borrowed from <a href="http://orteil.dashnet.org/cookieclicker/">Cookie Clicker</a>, an amazing and addictive cookie-themed game.</p>
|
||||
<h5>Libraries</h5>
|
||||
<p>This game is realised using a few libraries. Those are</p>
|
||||
<ul>
|
||||
<li><a href="http://angularjs.org">AngularJS</a></li>
|
||||
<li><a href="http://getbootstrap.com/">Bootstrap</a></li>
|
||||
<li><a href="http://fortawesome.github.io/">Fontawesome</a></li>
|
||||
<li><a href="http://jquery.com">jQuery</a></li>
|
||||
<li><a href="http://imulus.github.io/retinajs/">retina.js</a></li>
|
||||
<li><a href="https://github.com/ftlabs/fastclick">fastclick.js</a></li>
|
||||
</ul>
|
||||
<p class="small">Version: 0.6</p>
|
||||
|
||||
<p class="small bg-warning">This is a pre-release. <p>Science Alchemy is a card game where you work out the secret rule to determine which cards can be played. This game is based on <a href="http://www.logicmazes.com/games/eleusis/">Eleusis</a> by Robert Abbott and John Golden's <a href="http://www.logicmazes.com/games/eleusis/express.html">Eleusis</a> Express.
|
||||
|
||||
<h5>Authors</h5>
|
||||
<ul>
|
||||
<li><a href="https://github.com/gbiro">Gabor Biro</a></li>
|
||||
<li><a href="https://github.com/ibab">Igor Babuschkin</a></li>
|
||||
<li><a href="https://github.com/kdungs">Kevin Dungs</a></li>
|
||||
<li><a href="https://github.com/ntadej">Tadej Novak</a></li>
|
||||
<li><a href="https://github.com/zhangjiannan">Jiannan Zhang</a></li>
|
||||
<li><a href="https://github.com/wassname">wassname</a></li>
|
||||
</ul>
|
||||
<p>Feel free to get in touch with us via GitHub or by shooting us an email on<br><a href="mailto:particle-clicker@googlegroups.com">particle-clicker@googlegroups.com</a>.</p>
|
||||
<h5>Source</h5>
|
||||
<p>The source code of this game is freely available on <a href="https://github.com/particle-clicker/particle-clicker"><i class="fa fa-github"></i> GitHub</a> under the terms of an MIT license.</p>
|
||||
<p>Feel free to get in touch with us via GitHub or by shooting us an email on<br><a href="mailto:particle-clicker@wassname.org">particle-clicker@wassname.org</a>.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script>
|
||||
<script type="text/javascript" src="bower_components/jquery-ui/jquery-ui.js"></script>
|
||||
<script type="text/javascript" src="js/external/jquery.ui.touch-punch.min.js"></script>
|
||||
<script type="text/javascript" src="js/external/jquery.cookie-1.4.1.min.js"></script>
|
||||
<script type="text/javascript" src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
|
||||
|
||||
<script type="text/javascript" src="bower_components/angular/angular.js"></script>
|
||||
<script type="text/javascript" src="bower_components/angular-dragdrop/src/angular-dragdrop.js"></script>
|
||||
<script type="text/javascript" src="bower_components/angular-animate/angular-animate.js"></script>
|
||||
|
||||
<script type="text/javascript" src="js/external/retina.js"></script>
|
||||
<script type="text/javascript" src="js/external/fastclick.js"></script>
|
||||
|
||||
<script type="text/javascript" src="bower_components/chai/chai.js"></script>
|
||||
<script type="text/javascript" src="bower_components/lodash/dist/lodash.js"></script>
|
||||
<script type="text/javascript" src="bower_components/angular-ui-grid/ui-grid.js"></script>
|
||||
|
||||
<!-- Google Analytics -->
|
||||
<!-- <script>
|
||||
@@ -391,13 +329,5 @@
|
||||
</script> -->
|
||||
<!-- End Google Analytics -->
|
||||
|
||||
<script src="js/storage.js"></script>
|
||||
<script src="js/helpers.js"></script>
|
||||
<script src="js/analytics.js"></script>
|
||||
<script src="js/gameobjects.js"></script>
|
||||
<script src="js/rules.js"></script>
|
||||
<script src="js/ui.js"></script>
|
||||
<script src="js/game.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user