This is probably a kind of obscure topic but I found it interesting so I'm writing it up. It is not something I recommend you actually do. Rather, I think working through the topic will help illustrate some things about making 3d models for WebGL.
Someone asked how to make a bowling pin shape in WebGL. The smart answer is "Use a 3D modeling package like Blender, Maya, 3D Studio Max, Cinema 4D, etc. Use it to model a bowling pin, export, read the dat. (The OBJ format is relativly simple).
But, that got me thinking, what if they wanted to make a modeling package?
There's a few ideas. One is to make a cylinder and try to pinch it in the right places using sin waves applied in certain places. The problem with that idea you wouldn't get a smooth top. A standard cylinder is generated as a series of equally spaced rings but you'd need more rings where things are more curvy.
In a modeling package you'd make a bowling pin by making a 2d silhouette or rather a curved line that matches the edge of a 2d silhouette. You'd then lathe that into a 3d shape. By lathe I mean you'd spin it around some axis and generate points as you do. This lets you easily make any round objects like a bowl, a glass, a baseball bat, bottles, light bulbs, etc.
So, how do we do that? Well first we need some way to make a curve. Then we'd need to compute points on that curve. We'd then rotate those points around some axis using matrix math and build triangles from those points.
The most common kind of curve in computer graphics seems to be a bezier curve. If you've ever edited a curve in Adobe Illustrator or Inkscape or Affinity Designer or similar programs that's a bezier curve.
A bezier curve or rather a cubic bezier curve is formed by 4 points. 2 points are the end points. 2 points are the "control points".
Here's 4 points
We pick a number between 0 and 1 (called t
) where 0 = the beginning
and 1 = the end. We then compute the corresponding t
point
between each pair of points. P1 P2
, P2 P3
, P3 P4
.
In other words if t = .25
then we compute a point 25% of the way
going from P1
to P2
, another 25% of the way going from P2
to P3
and one more 25% of the way going from P3
to P4
.
You can drag the slider to adjust t
and you can also move points
P1
, P2
, P3
, and P4
.
We do the same for the resuling points. Compute t
points between Q1 Q2
and Q2 Q3
.
Finally we do the same for those 2 points and compute the t
point between
R1 R2
.
The positions of that red point make a curve.
So this is a cubic bezier curve.
Note that while the interpolation between points above and the process of making 3 points from 4, then 2 from 3, and finally 1 point from 2 works that's not the normal way. Instead someone plugged in all the math and simplified it to a formula like this
invT = (1 - t) P = P1 * invT^3 + P2 * 3 * t * invT^2 + P3 * 3 * invT * t^2 + P4 * t^3
Where P1
, P2
, P3
, P4
are the points like the examples above and P
is the red dot.
In a 2D vector art program like Adobe Illustrator when you make a longer curve it's actually made from many small 4 point curves like this. By default most apps lock the control points around a shared start/end point and make sure they are always opposite relative to the shared point.
See this example, move P3
or P5
and the code will move the other.
Notice the curve made by P1,P2,P3,P4
is a separate curve from
the one made by P4,P5,P6,P7
. It's just when P3
and P5
are on exact
opposite sides of P4
together they look like one continuous curve.
Most apps will then usually give you the option to stop locking them
together so you can get a sharp corner. Uncheck the lock checkbox
then drag P3
or P5
and it will become even more clear they are
separate curves.
Next up we need a way to generate points on a curve.
Using the formula above we can generate a point for
a given t
value like this.
function getPointOnBezierCurve(points, offset, t) {
const invT = (1 - t);
return v2.add(v2.mult(points[offset + 0], invT * invT * invT),
v2.mult(points[offset + 1], 3 * t * invT * invT),
v2.mult(points[offset + 2], 3 * invT * t * t),
v2.mult(points[offset + 3], t * t *t));
}
And we can generate a set of points for the curve like this
function getPointsOnBezierCurve(points, offset, numPoints) {
const points = [];
for (let i = 0; i < numPoints; ++i) {
const t = i / (numPoints - 1);
points.push(getPointOnBezierCurve(points, offset, t));
}
return points;
}
Note: v2.mult
and v2.add
are small JavaScript functions I included
to help do math with points.
In the diagram above you can choose a number of points. If the curve is sharp you'd want more points. If the curve is nearly a straight line though you'd probably want less points. One solution is to check how curvy a curve is. If it's too curvy then split it into 2 curves.
The splitting part turns out to be easy. If we look at the various
levels of interpolation again, the points P1
, Q1
, R1
, RED make one
curve and the points RED, R2
, Q3
, P4
make the other for any value of t.
In other words we can split the curve anywhere and get 2 curves
that match the original.
The second part is deciding if a curve needs to be split or not. Looking around the net I found this function that for a given curve decides how flat it is.
function flatness(points, offset) {
const p1 = points[offset + 0];
const p2 = points[offset + 1];
const p3 = points[offset + 2];
const p4 = points[offset + 3];
let ux = 3 * p2[0] - 2 * p1[0] - p4[0]; ux *= ux;
let uy = 3 * p2[1] - 2 * p1[1] - p4[1]; uy *= uy;
let vx = 3 * p3[0] - 2 * p4[0] - p1[0]; vx *= vx;
let vy = 3 * p3[1] - 2 * p4[1] - p1[1]; vy *= vy;
if(ux < vx) {
ux = vx;
}
if(uy < vy) {
uy = vy;
}
return ux + uy;
}
We can use that in our function that gets points for a curve. First we'll check if the cuvry is too curvy. If so we'll subdivide, if not we'll add the points in.
function getPointsOnBezierCurveWithSplitting(points, offset, tolerance, newPoints) {
const outPoints = newPoints || [];
if (flatness(points, offset) < tolerance) {
// just add the end points of this curve
outPoints.push(points[offset + 0]);
outPoints.push(points[offset + 3]);
} else {
// subdivide
const t = .5;
const p1 = points[offset + 0];
const p2 = points[offset + 1];
const p3 = points[offset + 2];
const p4 = points[offset + 3];
const q1 = v2.lerp(p1, p2, t);
const q2 = v2.lerp(p2, p3, t);
const q3 = v2.lerp(p3, p4, t);
const r1 = v2.lerp(q1, q2, t);
const r2 = v2.lerp(q2, q3, t);
const red = v2.lerp(r1, r2, t);
// do 1st half
getPointsOnBezierCurveWithSplitting([p1, q1, r1, red], 0, tolerance, outPoints);
// do 2nd half
getPointsOnBezierCurveWithSplitting([red, r2, q3, p4], 0, tolerance, outPoints);
}
return outPoints;
}
This algorithm does a good job of making sure we have enough points but it doesn't do such a great job of getting rid of unneeded points.
For that we turn to the Ramer Douglas Peucker algorithm I found on the net.
In that algorithm we take a list of points. We find the furthest point from the line formed by the 2 end points. Then we check if that point is further away from the line than some distance. If it's less than than that distance we just keep the 2 end points and discard the rest Otherwise we run the algorithm again, once with the points from the start to the furthest point and again from the furthest point to the end point.
function simplifyPoints(points, start, end, epsilon, newPoints) {
const outPoints = newPoints || [];
// find the most distance point from the endpoints
const s = points[start];
const e = points[end - 1];
let maxDistSq = 0;
let maxNdx = 1;
for (let i = start + 1; i < end - 1; ++i) {
const distSq = v2.distanceToSegmentSq(points[i], s, e);
if (distSq > maxDistSq) {
maxDistSq = distSq;
maxNdx = i;
}
}
// if that point is too far
if (Math.sqrt(maxDistSq) > epsilon) {
// split
simplifyPoints(points, start, maxNdx + 1, epsilon, outPoints);
simplifyPoints(points, maxNdx, end, epsilon, outPoints);
} else {
// add the 2 end points
outPoints.push(s, e);
}
return outPoints;
}
v2.distanceToSegmentSq
is a function that computes the distance squared from a point
to a line segment. We use the distance squared because it's faster to compute than
the actual distance. Since we only care which point is furthest the distance squared
will work just as well as the actual distance.
Here's that in action. Adjust the distance to see more points added or removed.
Back to our bowling pin. We could try to extend the code above into a full editor. It would need to be able to add and remove points, lock and unlock control points. It would need undo, etc... But there's an easier way. We can just use any of the major editors mentioned above. I used this online editor.
Here's the svg silhouette of a bowling pin I made.
It's made from 4 bezier curves. The data for that path looks like this
<path fill="none" stroke-width="5" d="
m44,434
c18,-33 19,-66 15,-111
c-4,-45 -37,-104 -39,-132
c-2,-28 11,-51 16,-81
c5,-30 3,-63 -36,-63
"/>
Interpreting that data we get these points.
___
44, 371, |
62, 338, | 1st curve
63, 305,___|__
59, 260,___| |
55, 215, | 2nd curve
22, 156,______|__
20, 128,______| |
18, 100, | 3rd curve
31, 77,_________|__
36, 47,_________| |
41, 17, | 4th curve
39, -16, |
0, -16,____________|
Now that we have the data for the curves we need to compute some points on them.
// gets points across all segments
function getPointsOnBezierCurves(points, tolerance) {
const newPoints = [];
const numSegments = (points.length - 1) / 3;
for (let i = 0; i < numSegments; ++i) {
const offset = i * 3;
getPointsOnBezierCurveWithSplitting(points, offset, tolerance, newPoints);
}
return newPoints;
}
We'd call simplifyPoints
on the result.
Now we need to spin them around. We decide how many divisions to make, for each division you use the matrix math to rotate the points around the Y axis. Once we've made all the points we connect them with triangles using indices.
// rotates around Y axis.
function lathePoints(points,
startAngle, // angle to start at (ie 0)
endAngle, // angle to end at (ie Math.PI * 2)
numDivisions, // how many quads to make around
capStart, // true to cap the start
capEnd) { // true to cap the end
const positions = [];
const texcoords = [];
const indices = [];
const vOffset = capStart ? 1 : 0;
const pointsPerColumn = points.length + vOffset + (capEnd ? 1 : 0);
const quadsDown = pointsPerColumn - 1;
// generate points
for (let division = 0; division <= numDivisions; ++division) {
const u = division / numDivisions;
const angle = lerp(startAngle, endAngle, u) % (Math.PI * 2);
const mat = m4.yRotation(angle);
if (capStart) {
// add point on Y axis at start
positions.push(0, points[0][1], 0);
texcoords.push(u, 0);
}
points.forEach((p, ndx) => {
const tp = m4.transformPoint(mat, [...p, 0]);
positions.push(tp[0], tp[1], tp[2]);
const v = (ndx + vOffset) / quadsDown;
texcoords.push(u, v);
});
if (capEnd) {
// add point on Y axis at end
positions.push(0, points[points.length - 1][1], 0);
texcoords.push(u, 1);
}
}
// generate indices
for (let division = 0; division < numDivisions; ++division) {
const column1Offset = division * pointsPerColumn;
const column2Offset = column1Offset + pointsPerColumn;
for (let quad = 0; quad < quadsDown; ++quad) {
indices.push(column1Offset + quad, column2Offset + quad, column1Offset + quad + 1);
indices.push(column1Offset + quad + 1, column2Offset + quad, column2Offset + quad + 1);
}
}
return {
position: positions,
texcoord: texcoords,
indices: indices,
};
}
The code above generates positions and texcoords, it then generates indices to make triangles
out of those. The capStart
and capEnd
specify whether or not generate cap points. Imagine
we're making a can. These options would specify whether or not to close the ends.
Using our simplified code we can generate WebGL buffers with this data like this
const tolerance = 0.15;
const distance = .4;
const divisions = 16;
const startAngle = 0;
const endAngle = Math.PI * 2;
const capStart = true;
const capEnd = true;
const tempPoints = getPointsOnBezierCurves(curvePoints, tolerance);
const points = simplifyPoints(tempPoints, 0, tempPoints.length, distance);
const arrays = lathePoints(points, startAngle, endAngle, divisions, capStart, capEnd);
const extents = getExtents(arrays.position);
if (!bufferInfo) {
bufferInfo = webglUtils.createBufferInfoFromArrays(gl, arrays);
Here's an example
Play with the sliders to see how they effect the result.
There's an issue though. Turn on triangles and you'll see the texture is not evenly
applied. This is because we based the v
texture coordinate on the index of the
points on the line. If they were evenly spaced that might work. They're not though
so we need to do something else.
We can walk the points and compute the total length of the curve and each point's
distance on that curve. We can then divide by the length and get a better value
for v
.
// rotates around Y access.
function lathePoints(points,
startAngle, // angle to start at (ie 0)
endAngle, // angle to end at (ie Math.PI * 2)
numDivisions, // how many quads to make around
capStart, // true to cap the top
capEnd) { // true to cap the bottom
const positions = [];
const texcoords = [];
const indices = [];
const vOffset = capStart ? 1 : 0;
const pointsPerColumn = points.length + vOffset + (capEnd ? 1 : 0);
const quadsDown = pointsPerColumn - 1;
+ // generate v coordniates
+ let vcoords = [];
+
+ // first compute the length of the points
+ let length = 0;
+ for (let i = 0; i < points.length - 1; ++i) {
+ vcoords.push(length);
+ length += v2.distance(points[i], points[i + 1]);
+ }
+ vcoords.push(length); // the last point
+
+ // now divide each by the total length;
+ vcoords = vcoords.map(v => v / length);
// generate points
for (let division = 0; division <= numDivisions; ++division) {
const u = division / numDivisions;
const angle = lerp(startAngle, endAngle, u) % (Math.PI * 2);
const mat = m4.yRotation(angle);
if (capStart) {
// add point on Y axis at start
positions.push(0, points[0][1], 0);
texcoords.push(u, 0);
}
points.forEach((p, ndx) => {
const tp = m4.transformPoint(mat, [...p, 0]);
positions.push(tp[0], tp[1], tp[2]);
* texcoords.push(u, vcoords[ndx]);
});
if (capEnd) {
// add point on Y axis at end
positions.push(0, points[points.length - 1][1], 0);
texcoords.push(u, 1);
}
}
// generate indices
for (let division = 0; division < numDivisions; ++division) {
const column1Offset = division * pointsPerColumn;
const column2Offset = column1Offset + pointsPerColumn;
for (let quad = 0; quad < quadsDown; ++quad) {
indices.push(column1Offset + quad, column1Offset + quad + 1, column2Offset + quad);
indices.push(column1Offset + quad + 1, column2Offset + quad + 1, column2Offset + quad);
}
}
return {
position: positions,
texcoord: texcoords,
indices: indices,
};
}
And here's the result
Those texture coordinates are still not perfect. We haven't decided what to do for the caps. This is yet another reason why you should just use a modeling program. We could come up with different ideas about how to compute uv coordinates for the caps but they'd probably not be all that useful. If you google for UV map a barrel you'll see that getting perfect UV coordinates is not so much a math problem as a data entry problem and you need nice tools to enter that data.
There's still one other thing we should do and that's add normals.
We could compute a normal for each point on the curve.
A normal is perpendicular to the tangent so it would be easy to use the tangents to genearate normals.
But, lets imagine we wanted to make a candle holder with a silhouette like this
There are many smooth areas but also many hard corners. How do we decide which normals to use? Worse, when we want a sharp edge we need extra vertices. Because vertices have both a position and a normal if we need a different normal for something at the same position then we need a different vertex. This is why if we're making a cube we actually need at least 24 vertices. Even though a cube only has 8 corners each face of the cube needs different normals at those corners.
When generating a cube it's easy to just generate the correct normals but for a more complex shape there's no easy way to decide.
All modeling programs have various options to generate normals. A common way is for every single vertex they average the normals of all the polygons that share that vertex. Except, they let the user choose some maximum angle. If the angle between one polygon shared by a vertex is greater than that maximum angle then they generate a new vertex.
Let's do that.
function generateNormals(arrays, maxAngle) {
const positions = arrays.position;
const texcoords = arrays.texcoord;
// first compute the normal of each face
let getNextIndex = makeIndiceIterator(arrays);
const numFaceVerts = getNextIndex.numElements;
const numVerts = arrays.position.length;
const numFaces = numFaceVerts / 3;
const faceNormals = [];
// Compute the normal for every face.
// While doing that, create a new vertex for every face vertex
for (let i = 0; i < numFaces; ++i) {
const n1 = getNextIndex() * 3;
const n2 = getNextIndex() * 3;
const n3 = getNextIndex() * 3;
const v1 = positions.slice(n1, n1 + 3);
const v2 = positions.slice(n2, n2 + 3);
const v3 = positions.slice(n3, n3 + 3);
faceNormals.push(m4.normalize(m4.cross(m4.subtractVectors(v1, v2), m4.subtractVectors(v3, v2))));
}
let tempVerts = {};
let tempVertNdx = 0;
// this assumes vertex positions are an exact match
function getVertIndex(x, y, z) {
const vertId = x + "," + y + "," + z;
const ndx = tempVerts[vertId];
if (ndx !== undefined) {
return ndx;
}
const newNdx = tempVertNdx++;
tempVerts[vertId] = newNdx;
return newNdx;
}
// We need to figure out the shared vertices.
// It's not as simple as looking at the faces (triangles)
// because for example if we have a standard cylinder
//
//
// 3-4
// / \
// 2 5 Looking down a cylinder starting at S
// | | and going around to E, E and S are not
// 1 6 the same vertex in the data we have
// \ / as they don't share UV coords.
// S/E
//
// the vertices at the start and end do not share vertices
// since they have different UVs but if you don't consider
// them to share vertices they will get the wrong normals
const vertIndices = [];
for (let i = 0; i < numVerts; ++i) {
const offset = i * 3;
const vert = positions.slice(offset, offset + 3);
vertIndices.push(getVertIndex(vert));
}
// go through every vertex and record which faces it's on
const vertFaces = [];
getNextIndex.reset();
for (let i = 0; i < numFaces; ++i) {
for (let j = 0; j < 3; ++j) {
const ndx = getNextIndex();
const sharedNdx = vertIndices[ndx];
let faces = vertFaces[sharedNdx];
if (!faces) {
faces = [];
vertFaces[sharedNdx] = faces;
}
faces.push(i);
}
}
// now go through every face and compute the normals for each
// vertex of the face. Only include faces that aren't more than
// maxAngle different. Add the result to arrays of newPositions,
// newTexcoords and newNormals, discarding any vertices that
// are the same.
tempVerts = {};
tempVertNdx = 0;
const newPositions = [];
const newTexcoords = [];
const newNormals = [];
function getNewVertIndex(x, y, z, nx, ny, nz, u, v) {
const vertId =
x + "," + y + "," + z + "," +
nx + "," + ny + "," + nz + "," +
u + "," + v;
const ndx = tempVerts[vertId];
if (ndx !== undefined) {
return ndx;
}
const newNdx = tempVertNdx++;
tempVerts[vertId] = newNdx;
newPositions.push(x, y, z);
newNormals.push(nx, ny, nz);
newTexcoords.push(u, v);
return newNdx;
}
const newVertIndices = [];
getNextIndex.reset();
const maxAngleCos = Math.cos(maxAngle);
// for each face
for (let i = 0; i < numFaces; ++i) {
// get the normal for this face
const thisFaceNormal = faceNormals[i];
// for each vertex on the face
for (let j = 0; j < 3; ++j) {
const ndx = getNextIndex();
const sharedNdx = vertIndices[ndx];
const faces = vertFaces[sharedNdx];
const norm = [0, 0, 0];
faces.forEach(faceNdx => {
// is this face facing the same way
const otherFaceNormal = faceNormals[faceNdx];
const dot = m4.dot(thisFaceNormal, otherFaceNormal);
if (dot > maxAngleCos) {
m4.addVectors(norm, otherFaceNormal, norm);
}
});
m4.normalize(norm, norm);
const poffset = ndx * 3;
const toffset = ndx * 2;
newVertIndices.push(getNewVertIndex(
positions[poffset + 0], positions[poffset + 1], positions[poffset + 2],
norm[0], norm[1], norm[2],
texcoords[toffset + 0], texcoords[toffset + 1]));
}
}
return {
position: newPositions,
texcoord: newTexcoords,
normal: newNormals,
indices: newVertIndices,
};
}
function makeIndexedIndicesFn(arrays) {
const indices = arrays.indices;
let ndx = 0;
const fn = function() {
return indices[ndx++];
};
fn.reset = function() {
ndx = 0;
};
fn.numElements = indices.length;
return fn;
}
function makeUnindexedIndicesFn(arrays) {
let ndx = 0;
const fn = function() {
return ndx++;
};
fn.reset = function() {
ndx = 0;
}
fn.numElements = arrays.positions.length / 3;
return fn;
}
function makeIndiceIterator(arrays) {
return arrays.indices
? makeIndexedIndicesFn(arrays)
: makeUnindexedIndicesFn(arrays);
}
In the code above first we genearte normals for each face (each triangle) from the original points. We then generate a set of vertex indices to find points that are the same. That's because as we rotated the points the first point and the last point should match up but they have differnet UV coordinates so they are not the same point. To compute the vertex normals we need them to be considered the same point.
Once that's done, for each vertex, we make a list of all the faces it's used by.
Finally we average the normals of all the faces each vertex uses excluding ones that are
more than maxAngle
different and genearte a new set of vertices.
Here's the result
Notice we get sharp edges where we want them. Make the maxAngle
bigger and you'll see those edges
get smoothed out when the neighboring faces start getting included in the normal calculations.
Also try adjusting the divisions
to something like 5 or 6 then adjust the maxAngle
until the
edges around are hard but the parts you want smooth are still smooth. You can also set the mode
to lit
to see what the object would look like with lighting, the reason we needed normals.
We learned if you want to make 3D data USE A 3D MODELING PACKAGE!!! 😝
To do anything really useful you'd likely need a real UV editor. Dealing the the caps as well is something a 3D editor would help with. Instead of using a limited set of options when lathing you'd use other features of the editor to add caps and generate easier UVs for the caps. 3d editors also support extruding faces and extruding along a path which if you take a look it should be pretty obvious how they work based on the lathe example above.
I wanted to mention I couldn't have done this without this awesome page about bezier curves.


Atlanta, Georgia
Kendeda Building
This "living building" on Georgia Tech's campus is home to a blueberry orchard, honeybees, and more than 900 solar panels.
by tjmuehlemanOn the west side of Georgia Tech’s campus sits the largest “living building” in the southern United States. Part of the School of Architecture at Georgia Tech, the recently-opened Kendeda Building for Innovative Sustainable Design building is home to classrooms, event spaces, an apiary, and a blueberry orchard.
From the outside, the building feels almost out of place for its urban surroundings. A combination of natural wood and cement with broad, large windows, the building seems like it should be in the middle of the woods instead of on a college campus in Atlanta. But that’s part of the design. Using reclaimed wood, windows that help regulate the temperature, and a sophisticated water reclamation system, the building is designed to barely make a blip on the ecological radar.
Salvaged materials mean this new building incorporates a lot of campus history. The bathroom tile was sourced from a roof update at the Georgia Tech Alumni Association building and the staircase treads are heart pine joists that were salvaged from a renovation of the 140-year-old Tech Tower.
The Kendeda Building also has a green roof, bees to produce honey, and more than 900 solar panels. Construction was largely completed in 2019, and the building opens for classes in January 2020.
Know Before You Go
The building is open to the public during normal business hours. A schedule of public tours can be found on the building’s website, and private tours are available by request.
It is about a mile from the nearest Marta station (Midtown station), about 2.2 miles from Ponce City Market (a great place for drinks and shopping). Parking can be tough, so walking or taking public transportation is recommended.
Community Discussion
-
No Comments Yet
Start the discussion.
forum Visit our forums.


Specify an image file located on your workstation or a TFTP server. An image file contain switch firmware. The image that you upload will be unpacked from the image file and added to the appropriate list above.
Select the image file saved on the workstation storage medium to upload.
{{file ? '' : 'Upload complete. Check image above.'}}
Specify both the TFTP server IP address and the image file name stored on it to download.
{{download_error_msg}}
Download complete. Check image tables above.
Delete firmware {{delete_image_version}}?
Switch firmware file v{{activate_image_version}} will be used in the new firmware.
Switch image {{activate_image_id}}-{{activate_image_version}} is updating now. Please wait.


PROFILE
3
NOTES
STUDY GROUP
NETWORKING
SIGN OUT
or Upload Notes
TITLE
TOPIC
COURSE
DOWNLOAD
binary search
algorithms
computer science
Download
stacks
algorithms
computer science
Download
Hamlet
shakespeare
english
Download
fractions
numbers
maths
Download


Installation
Download and include in your projects.
<script src="/js/backbone.iosync.js"></script>
<script src="/js/backbone.iobind.js"></script>
Or use the minimized versions.
<script src="/js/backbone.iosync.min.js"></script>
<script src="/js/backbone.iobind.min.js"></script>
Dependancies
Backbone.sync Replacement
The Backbone.sync replacement for socket.io, backbone.iosync.js
, is a drop-in replacement for Backbone.sync that
will make Backbone use socket.io for all normal CRUD operations.
Namespaces / Urls
Backbone has a dedicated attribute, urlRoot
for models, and url
for collections, that is used
by the default sync method to direct AJAX request. ioSync uses this same attribute to create a
namespace tag for that model.
For Example: If your collection url is 'posts' or '/posts', the events to listen for server-side will be:
posts:create
posts:read
posts:update
posts:delete
As with the default sync method, for a given model, ioSync will default to the url
of the collection
that model is a part of, else it will use the models urlRoot
.
If your url has a depth of more than one, only the first will be used. Example: /posts/comments
will still only have a namespace of posts
.*
RPC / Callbacks
This replacement assumes that you are using socket.io's RPC (callback) formula for these events. Examine this psuedo-code:
socket.on('posts:read', function (data, callback) {
db.query({_id: data.id}, function (err, model) {
if (err) {
callback(err);
} else {
// ... some data scrubbing
callback(null, model);
}
});
});
The callback accepts two parameters: error
and model
. If no error has occurred, send null
for error
.
The model
should be a JSON representation of the client-side model's attributes.
Binding Custom Events
The primary function for Backbone.ioBind is to make it easy to create client-side listeners for server-side socket.io events. The most likely use case for this is to broadcast changes made by one client to all other clients watching a particular data object.
The following samples are from the example app that demonstrates a very basic usage scenario.
ioBind
The ioBind function is available for both Models and Collections, and behaves identically in both scenarios.
// Example Model.extend
urlRoot: 'todo',
socket: window.socket,
initialize: function () {
_.bindAll(this, 'serverChange', 'serverDelete', 'modelCleanup');
this.ioBind('update', this.serverChange, this);
this.ioBind('delete', this.serverDelete, this);
}
// Example Collection.extend
url: 'todos',
socket: window.socket,
initialize: function () {
_.bindAll(this, 'serverCreate', 'collectionCleanup');
this.ioBind('create', this.serverCreate, this);
}
The primary difference between ioBind
on Models and Collection is the event string that is listened for.
On models, the event string includes the Model id
, whereas on collection it is simply the collection namespace.
The above example will respond to the following socket.io events.
// Model events
socket.emit('todo/' + todo_obj.id + ':update', todo_obj);
socket.emit('todo/' + todo_obj.id + ':delete', todo_obj);
// Collection events
socket.emit('todos:create', todo_obj);
Usage Guideline
Model binding without ID: Do NOT bind to Models that do NOT have an id
assigned. This will cause for extra listeners
and cause potentially large memory leak problems. See the example app for one possible workaround.
Namespace construction: When constructing the namespace, as with the the ioSync method, for a given model ioBind
will default to the url
of the collectionthat model is a part of, else it will use the models urlRoot
.
Reserved events: Do NOT bind to reserved backbone events, such as change
, remove
, and add
. Proxy these
events using different event tags such as update
, delete
, and create
.
Example App
Overview
Done. is a task application that keeps itself synchronized across all browser instances. This app was built to demonstrate the basic usage of Backbone.ioBind and ioSync. The code is intended to be easy to follow and is heavily commented.
Installation
To start off, you are going to need to clone the repo.
$ git clone https://github.com/logicalparadox/backbone.iobind.git
Before you can run anything you need to install the dev dependancies, such as Express, Seed, and Socket.io.
$ cd backbone.iobind
$ npm install
Optionally, you should install the build tool, should you want to make changes to backbone.iobind or backbone.sync for socket.io. The tool used is jake
and it should be installed in the global npm space.
$ [sudo] npm -g install jake
If you installed jake, then simply run the following command to start up the example app.
$ jake serve
Note: jake -T
shows you a list of all available commands.
If you did not install jake, then start up the example app using node.
$ node example/app.js
For Contributors
Please avoid making changes to the dist
versions of backbone.iobind. All changes to the library are to be
made to lib/*.js
and then packaged for the browser using the build tools.
Building
Build tool is built in jake.
[sudo] npm install jake -g
Clone this repo:
git clone https://github.com/logicalparadox/backbone.iobind
Install development/build dependancies (Ie: folio.:
npm install
Run jake
jake
for detailed information, jake build:all
to build all files.


--- layout: page title: Activity Graphs permalink: /activity-graphs/ menu_index: 5 menu_visible: false ---


Page 2 of 7
going to be
shooting through a window or a mirror, AutoFocus will get confused
between the
action and any reflections.
ii. Viewfinder
The viewfinder
has a separate focus that is in no way connected to the focus of
the lens. You
can adjust the focus on the viewfinder by sliding a little knob on
the under side
of the viewfinder. Focus the viewfinder so that the text and
icons are in
focus, then you'll be able to tell when the main lens is in focus.
5. White
Balance
Colour, as
observed by a camera, depends on the light source that illuminates it. This is
due in part to the camera
design, but
mostly due to physics. Ignoring math and
theory, it comes down to this: various light sources operate at
different
temperatures, and this changes the colour slightly. The major light sources are
sunlight, tungsten (regular
light bulbs) and
fluorescent. The AG-456 adjusts for the colour differences through a feature
known as "white
balancing"
you define white for the camera and it corrects every other colour. To "white
balance" the camera, you
need to fill the
frame with a white object and hold down the "W.B." button until the icon in the
viewfinder stops
flashing (again,
like focus, the camera must be in "manual" mode). If you don't have a white
wall, or a white sheet
of paper, just
put the lens cap on and point the camera at the light source. If the camera
balances tungsten as
white, then the
sunlight will look blue. Inversely, if the camera decides that sunlight is
white, then the tungsten
light will look
orange. Fluorescents look green if they aren't balanced properly. To ensure the
camera balances
correctly, it's
best to use only one type of lighting. If you can do that, you can try and
balance the lighting sources
directly, such
as using a blue tungsten light bulb to match sunlight.
6. Zoom
Practically
every camera in use today comes equipped with a zoom lens, which can simulate
all sorts
of standard
fixed lenses, such as wide-angle or telephoto. Although a zoom is a nifty
effect to play
around with on
the camera, you won't see it very often in professional work. It's a very
unnatural
effect. Why does the camera have a zoom lens? It's
cheaper and more compact than carrying
around a pile of
different lenses. It's best to treat the zoom lens as a collection of various
fixed
lenses. Zoom the
camera to get your subject to the right size and then press the record button.
In
the wide-angle
setting ("zoomed out") the focus isn't very sensitive. Instead, go to the
telephoto
setting ("zoomed
in"), focus on your subject, and zoom out to the appropriate size. This will
ensure
that the focus
is set on your subject, giving it a very crisp image.
7. Headphones
It's very easy
to get caught up in making sure the camera is recording video properly, the
image
looks good, and
so on. However, audio is just as important. The only way to make sure the audio
sounds good, is
to use a pair of headphones to listen to what the camera is receiving. The
AG-456
has a "Y" shaped
cable that fits into the two audio jacks on the back of the camera and allows a
pair
of headphones to
be plugged in. Check the audio monitor switch on the back of the camera to see
which audio
format you are monitoring (Normal, Hi-fi or both "Mix").
8. Tripod
Tripods should
be used whenever possible, as they provide the much needed stability for good
shots.
Extend the
tripod legs all the way out and try to spread the legs as far apart as possible
this is the
easiest way to
get the camera to the height you want. Most of the tripods have a quick release
plate
which screws
into the bottom of the camera. The head of the tripod should have knobs to
adjust the
resistance to
motion in the pan, tilt and pedestal axes. Don't over tighten these knobs when
locking
the tripod in
place. The same goes for the leg lock knobs. Finally, if you're going to move
the
camera (i.e. a
pan or tilt) use the lever attached to the tripod head don't push or
manipulate the
camera.
If you can't
film with a tripod, there are several techniques that will help stabilize your
shot. First,
keep the camera
in a wide-angle setting ("zoomed out"). Also, try to find something to lean or
prop
the camera up
against. Try to relax, and keep you elbows and knees bent.
9. Equipment
Care
Whenever you are
out on a shoot, make sure you treat the equipment as nicely as possible. New
equipment will
remain new longer and old equipment will work longer. To this end, keep the
following
tips in mind
whenever you are shooting:
i.
Don't Force
Anything
If you're
getting a lot of resistance from the camera, tripod or other equipment,
chances are
you're doing something wrong. For instance, the batteries have a
special notch in
them to ensure that the batteries are inserted properly. Trying
to force the
battery while in an incorrect alignment will only damage the battery
and the camera.


Bristol City's Championship rivals Leeds United set for huge £120m cash injection in promotion boost - reports
It could play a big part in the January transfer window
by David ByromParis Saint-Germain's Qatari owners are reportedly on the verge of sealing a potential £120m takeover of Leeds United.
The Mirror report that Bristol City's Championship rivals are set to receive around£10m for a stake in the Elland Road club, which would allow them to complete the takeover if Leeds are promoted to the Premier League.
Leeds have been in terrific form this season and experts rank their chances of promotion highly.
Current owner Andrea Radrizzani wants £80m to sell the club now but that fee would go up by £40m if the club are promoted.
It is believed that Qatari Sports Investment (QSI) see the added sum as worth paying, instead of taking an £80m risk now following a string of unsuccessful promotion bids.
Buying a stake in the club now would act as a deposit for a full takeover should the club get promoted.
However, in the short term, it will create added money for Marcelo Bielsa to spend in January.
It could be bad news for Bristol City, with both clubs said to be keen on a striker and the Whites suddenly having extra spending power.
Get lots more news, opinion and transfer updates on our Bristol City FC page and add a bookmark to find it quickly next time.


Online Admission for Colleges
Home

Login

Cut offs

Colleges

Your Profile

Login
Already a user?
User Name:
Password:

Create username and password
register


---
layout: default
title: Alfredo Ramirez - Computer Science Tutoring
---
Lessons
{% for post in site.posts %}
{% if post.category == 'lesson' %}
- {{ post.date | date_to_string }} » {{ post.title }}
{% endif %}
{% endfor %}
Labs
{% for post in site.posts %}
{% if post.category == 'lab' %}
- {{ post.date | date_to_string }} » {{ post.title }}
{% endif %}
{% endfor %}
Homework
{% for post in site.posts %}
{% if post.category == 'homework' %}
- {{ post.date | date_to_string }} » {{ post.title }}
{% endif %}
{% endfor %}
Cool Stuff
Here are links to some cool things I figure you may like or find interesting that are
related to the topics we cover.
-
Check out this
book
on the 'Hacker Ethic'. A seminal work by Steven Levy.
-
For another interesting (and shorter) perspective on 'ethical hacking', check out this
Forbes Article.
-
Bill Gates did an AMA on
Reddit
. For the record, I don't like Reddit.


--- layout: post permalink: coolpacifiers™.html Tags: Array NameOfCoupon: CoolPacifiers™ Cash Back Summary: See our CoolPacifiers™ Coupon Code, CoolPacifiers™ Rebate, CoolPacifiers™ Promo Code, CoolPacifiers™ Discount, CoolPacifiers™ Coupon Cash Back Rebate here. MetaKeywords: CoolPacifiers™ Coupon Code, CoolPacifiers™ Rebate, CoolPacifiers™ Promo Code, CoolPacifiers™ Cash Back Rebate, CoolPacifiers™ Discount, CoolPacifiers™ Coupon Image: images/12133.jpg LinkURL: http://www.shareasale.com/r.cfm?b=75681&u=412002&m=12133 affiliate_url_link: http://www.icouponblog.com/jane.php?id=2693 thesis_readmore: See the CoolPacifiers™ Coupon thesis_thumb: http://www.icouponblog.com/tn.php?merchantURL=coolpacifiers.com Title: Save 10% - CoolPacifiers™ Coupon Code for coolpacifiers.com. CoolPacifiers™ Rebate & Discount thesis_description: Our CoolPacifiers™ Discount Coupon Code for coolpacifiers.com. We have the best CoolPacifiers™ Rebate anywhere. thesis_keywords: CoolPacifiers™, CoolPacifiers™ Coupon Code, CoolPacifiers™ Discount, CoolPacifiers™ Rebate product_name: CoolPacifiers™ hop_url: http://www.icouponblog.com/hop.php?id=2693 ---
If you have a small baby and are looking for the perfect pacifier, visit www.coolpacifiers.com. It is the ideal place to buy hygienic, non toxic, natural bite resistant pacifiers that will not harm the mouth and teeth of the baby. You will love cool pacifiers. They are adorable, cute and so practical for your little ones. You can also personalize the pacifier by putting the babies name on it. Get the best pacifier online from www.coolpacifiers.com. Use our discount coupons to get a great price!
If you want a pacifier that can be personalized is cute and different from everyone else shop at www.coolpacifiers.com is the best website to buy pacifiers. The pacifiers are cool and inexpensive, yet perfect for a little baby. They are bite resistant, made from safe, non-toxic materials. They form naturally in the mouth which satisfies a baby’s need for supplemental sucking.  Get a cool pacifier at www.coolpacifiers.com which reads, ‘My mom rocks’ or ‘My mom’s hot’. Check out the website you will love it.
if you want a pacifier that is safe, sturdy naturally designed then checks out www.coolpacifiers.com. It is the ultimate pacifier, designed for the baby’s needs. You can personalize the pacifier and put a message to make it a memorable piece. Bring peace and tranquility to your baby without harming his mouth and gums. Coolpacifiers.com is the best pacifier for your baby.


| PostgreSQL 9.0.10 Documentation | ||||
|---|---|---|---|---|
| Prev | Up | Chapter 4. SQL Syntax | Next |
PostgreSQL allows functions that have named parameters to be called using either positional or named notation. Named notation is especially useful for functions that have a large number of parameters, since it makes the associations between parameters and actual arguments more explicit and reliable. In positional notation, a function call is written with its argument values in the same order as they are defined in the function declaration. In named notation, the arguments are matched to the function parameters by name and can be written in any order.
In either notation, parameters that have default values given in the function declaration need not be written in the call at all. But this is particularly useful in named notation, since any combination of parameters can be omitted; while in positional notation parameters can only be omitted from right to left.
PostgreSQL also supports mixed notation, which combines positional and named notation. In this case, positional parameters are written first and named parameters appear after them.
The following examples will illustrate the usage of all three notations, using the following function definition:
CREATE FUNCTION concat_lower_or_upper(a text, b text, uppercase boolean DEFAULT false) RETURNS text AS $$ SELECT CASE WHEN $3 THEN UPPER($1 || ' ' || $2) ELSE LOWER($1 || ' ' || $2) END; $$ LANGUAGE SQL IMMUTABLE STRICT;
Function concat_lower_or_upper
has two mandatory
parameters, a and b. Additionally
there is one optional parameter uppercase which defaults
to false. The a and
b inputs will be concatenated, and forced to either
upper or lower case depending on the uppercase
parameter. The remaining details of this function
definition are not important here (see Chapter 35 for
more information).
Positional notation is the traditional mechanism for passing arguments to functions in PostgreSQL. An example is:
SELECT concat_lower_or_upper('Hello', 'World', true); concat_lower_or_upper ----------------------- HELLO WORLD (1 row)
All arguments are specified in order. The result is upper case since uppercase is specified as true. Another example is:
SELECT concat_lower_or_upper('Hello', 'World'); concat_lower_or_upper ----------------------- hello world (1 row)
Here, the uppercase parameter is omitted, so it receives its default value of false, resulting in lower case output. In positional notation, arguments can be omitted from right to left so long as they have defaults.
In named notation, each argument's name is specified using := to separate it from the argument expression. For example:
SELECT concat_lower_or_upper(a := 'Hello', b := 'World'); concat_lower_or_upper ----------------------- hello world (1 row)
Again, the argument uppercase was omitted so it is set to false implicitly. One advantage of using named notation is that the arguments may be specified in any order, for example:
SELECT concat_lower_or_upper(a := 'Hello', b := 'World', uppercase := true); concat_lower_or_upper ----------------------- HELLO WORLD (1 row) SELECT concat_lower_or_upper(a := 'Hello', uppercase := true, b := 'World'); concat_lower_or_upper ----------------------- HELLO WORLD (1 row)
The mixed notation combines positional and named notation. However, as already mentioned, named arguments cannot precede positional arguments. For example:
SELECT concat_lower_or_upper('Hello', 'World', uppercase := true); concat_lower_or_upper ----------------------- HELLO WORLD (1 row)
In the above query, the arguments a and b are specified positionally, while uppercase is specified by name. In this example, that adds little except documentation. With a more complex function having numerous parameters that have default values, named or mixed notation can save a great deal of writing and reduce chances for error.


Ticket ID: 409788
Name:
Parker Seidel
No active support
Email:
<EMAIL_ADDRESS>Response Time:
72hours, 60hours left
Last Action
Never been locked.
Link to public post
Status:
Not answered


NetPAD
the web app, the URL http://pad.aityahya.ml, the code and it's author(me) are NOT in any way associated with notepad — the text editor for Windows — it's products, business or authors.
I did NOT deliberately choose the name with the intent of deceiving users or in any manner take advantage of the success of the above mentioned software to otherwise promote or sell my web app.
My purpose when i built this app was for personal use, experimentation and to share the resulting code, the exposure it has gotten on social media and tech blogs has not been my doing.
It just happens that choosing names for side projects like these is sometimes the hardest part in all the process. NetPAD seemed a good fit, and at the time i wasn't aware of other existing text editors(although not similar in function or form) with the same name.
Yours sincerely,
Abdelaziz Ait Yahya - aityahya.ml


rspec-core
rspec-core provides the structure for writing executable examples of how your
code should behave, and an rspec
command with tools to constrain which
examples get run and tailor the output.
install
gem install rspec # for rspec-core, rspec-expectations, rspec-mocks
gem install rspec-core # for rspec-core only
rspec --help
basic structure
RSpec uses the words "describe" and "it" so we can express concepts like a conversation:
"Describe an order."
"It sums the prices of its line items."
RSpec.describe Order do
it "sums the prices of its line items" do
order = Order.new
order.add_entry(LineItem.new(:item => Item.new(
:price => Money.new(1.11, :USD)
)))
order.add_entry(LineItem.new(:item => Item.new(
:price => Money.new(2.22, :USD),
:quantity => 2
)))
expect(order.total).to eq(Money.new(5.55, :USD))
end
end
The describe
method creates an ExampleGroup. Within the
block passed to describe
you can declare examples using the it
method.
Under the hood, an example group is a class in which the block passed to
describe
is evaluated. The blocks passed to it
are evaluated in the
context of an instance of that class.
nested groups
You can also declare nested nested groups using the describe
or context
methods:
RSpec.describe Order do
context "with no items" do
it "behaves one way" do
# ...
end
end
context "with one item" do
it "behaves another way" do
# ...
end
end
end
aliases
You can declare example groups using either describe
or context
.
For a top level example group, describe
and context
are available
off of RSpec
. For backwards compatibility, they are also available
off of the main
object and Module
unless you disable monkey
patching.
You can declare examples within a group using any of it
, specify
, or
example
.
shared examples and contexts
Declare a shared example group using shared_examples
, and then include it
in any group using include_examples
.
RSpec.shared_examples "collections" do |collection_class|
it "is empty when first created" do
expect(collection_class.new).to be_empty
end
end
RSpec.describe Array do
include_examples "collections", Array
end
RSpec.describe Hash do
include_examples "collections", Hash
end
Nearly anything that can be declared within an example group can be declared
within a shared example group. This includes before
, after
, and around
hooks, let
declarations, and nested groups/contexts.
You can also use the names shared_context
and include_context
. These are
pretty much the same as shared_examples
and include_examples
, providing
more accurate naming when you share hooks, let
declarations, helper methods,
etc, but no examples.
metadata
rspec-core stores a metadata hash with every example and group, which contains their descriptions, the locations at which they were declared, etc, etc. This hash powers many of rspec-core's features, including output formatters (which access descriptions and locations), and filtering before and after hooks.
Although you probably won't ever need this unless you are writing an extension, you can access it from an example like this:
it "does something" do
expect(example.[:description]).to eq("does something")
end
described_class
When a class is passed to describe
, you can access it from an example
using the described_class
method, which is a wrapper for
example.metadata[:described_class]
.
RSpec.describe Widget do
example do
expect(described_class).to equal(Widget)
end
end
This is useful in extensions or shared example groups in which the specific
class is unknown. Taking the collections shared example group from above, we can
clean it up a bit using described_class
:
RSpec.shared_examples "collections" do
it "is empty when first created" do
expect(described_class.new).to be_empty
end
end
RSpec.describe Array do
include_examples "collections"
end
RSpec.describe Hash do
include_examples "collections"
end
the rspec
command
When you install the rspec-core gem, it installs the rspec
executable,
which you'll use to run rspec. The rspec
command comes with many useful
options.
Run rspec --help
to see the complete list.
store command line options .rspec
You can store command line options in a .rspec
file in the project's root
directory, and the rspec
command will read them as though you typed them on
the command line.
autotest integration
rspec-core no longer ships with an Autotest extension, if you require Autotest
integration, please use the rspec-autotest
gem and see rspec/rspec-autotest
for details
get started
Start with a simple example of behavior you expect from your system. Do this before you write any implementation code:
# in spec/calculator_spec.rb
RSpec.describe Calculator do
describe '#add' do
it 'returns the sum of its arguments' do
expect(Calculator.new.add(1, 2)).to eq(3)
end
end
end
Run this with the rspec command, and watch it fail:
$ rspec spec/calculator_spec.rb
./spec/calculator_spec.rb:1: uninitialized constant Calculator
Implement the simplest solution:
# in lib/calculator.rb
class Calculator
def add(a,b)
a + b
end
end
Be sure to require the implementation file in the spec:
# in spec/calculator_spec.rb
# - RSpec adds ./lib to the $LOAD_PATH
require "calculator"
Now run the spec again, and watch it pass:
$ rspec spec/calculator_spec.rb
.
Finished in 0.000315 seconds
1 example, 0 failures
Use the documentation
formatter to see the resulting spec:
$ rspec spec/calculator_spec.rb --format doc
Calculator
#add
returns the sum of its arguments
Finished in 0.000379 seconds
1 example, 0 failures


{projects().length, plural, =0 {Currently there is no open project.} =1 {Currently there is 1 open project.} other {Currently there are {{projects().length}} open projects.}}


Relative expression of 10 selected differentially expressed genes. ( A) Expression of 4 genes in H1 vs H8. ( B) Expression of 6 genes in H3 vs H8. H1, H3 and H8 represent 1, 3 and 8 months old ovaries, respectively. The error bars represent the standard deviation. Bars with an asterisk (**) indicate significant difference by t test at 5% probability.


Piers Morgan slams claims Rule Britannia should be banned
He said it "stirs the soul"
by Richard BellPresenter Piers Morgan butted heads with a guest on Good Morning Britain who suggested the the song Rule, Britannia! should be banned.
The GMB host, 54, was incensed on Wednesday's (13.11.19) episode at the suggestion that the patriotic tune - which dates back to 1700s - should be kept off the airwaves.
The Apprentice star Joanna Jarjue was on to debate the issue and told Piers: "The song was written in the middle of the 1700s and that was when Britain was fully partaking in the slave trade.
Read more: Piers Morgan rages at Greggs over 'diet doughnuts'
"So to have lyrics like rule Britannia and Britons will never be slaves while then fully participating in slavery, in 2019 I find that completely outdated."
Asked by Piers if she would ban the song, Joanna replied: "Yeah, I would! Well, banning it completely... if people want to, kind of, sing it in their own private homes..."
Piers, clearly annoyed by the idea, demanded: "You'd ban it from the airwaves? We'd never play it in public again? One of the greatest patriotic anthems this nation has ever had."
But Joanna questioned why it was even "patriotic".
Piers offered: "Because it stirs the soul and it reminds us of the fact we're a great country!"
Joanna also told him: "What I think is it reminds us of colonial rule. When I listen to it, especially on days like Remembrance Day, I think it's a little bit insensitive, I think for the fallen soldiers, especially the ones from the Commonwealth."
GMB shared a clip of the conversation on Twitter and a number of viewers were outraged at the suggestion that Rule, Britannia! should be banned.
One said: "Not often I agree with @piersmorgan... it's a no from me."
Another wrote: "They fought and fell so these little snits could voice their opinions - makes me wonder sometimes though!"
Read more: Piers Morgan takes swipe at X Factor after his appearance on The Chase smashed ratings
A third put: "At the end of the day, someone will take offence at something all the time. I'm offended by wasting oxygen on people who continually take offence."
Someone else tweeted: "It is wrong to eradicate memories from history. They are there to be learnt from."
The debate followed a suggestion from singer Lily Allen that Rule, Britannia! should be banned.
Leave us a comment on our Facebook page @EntertainmentDailyFix and let us know what you think of this story.


About
Projects
Contact
Manage, Deploy.
Lorem ipsum sit dolor amet is a dummy text used by typography industry
Get Started
Great power comes with great Responsability
Lorem ipsum sit dolor amet is a dummy text used by typography industry
Online App builder
This is some explanatory text that is on two rows
Free Trial
Cloud deployment
This is some explanatory text that is on two rows
Get Started
Pluggable tools
This is some explanatory text that is on two rows
Get Started
Drop us a line or two !
Lorem ipsum sit dolor amet is a dummy text used by typography industry


Try a game
Magic Numbers
Magic Colors
How To Play
hide sidebar
show sidebar
Magic Color
We are developers from India.
Support:ggbhat@msn.com


It's a 14 days special Bootcamp for the people who want to learn the core of JavaScript Programming!
We love this course because it teaches us the latest JavaScript programming!


United States Marine Corps, 2019
This is the last face you’ll see before being shipped off to Saudi Arabia to “ensure the free flow of resources necessary to support the global economy.”
by Chris Menahan | Information LiberationThis is the last face you’ll see before being shipped off to Saudi Arabia to “ensure the free flow of resources necessary to support the global economy.”
There’s no word yet on whether these troops will be forced to wear high heels during their training.
Join Alex Jones for his Live Sunday broadcast from InfoWars HQ ATX Get DNA Force Plus 50% off and get a free bottle of Brain Force Plus now!


We optimize tables!
- implement B2B markets
- cultivate proactive content
- engage end-to-end action-items
- engineer mission-critical niches
- incentivize B2B niches
- scale holistic channels
- maximize interactive niches
- matrix cross-media relationships
- embrace ubiquitous applications
- whiteboard web-enabled eyeballs
- revolutionize mission-critical solutions
- syndicate ubiquitous channels
- architect dynamic communities
- morph global interfaces
- revolutionize turn-key functionalities


ACE
Home
messages
{% user %}
Blog Post
Pacchu
Profile page
Edits
Name
Email Address
Phone Number
Message
Send


description
A description of a widget is a pop-up block that can be used to detail the content and function of the corresponding widget. Each widget comes with the method
describe
that binds the description menu to the right-click event on the widget.


Feauture
Details
Key Features
100% Real Colour - Ground-breaking Quantum Dot technology delivers perfect 100% colour volume,
HDR1500,
Boundless Design,
Q Colour - Discover a world of colour volume that will change your thinking about TV
Display Size
55 inch
Resolution
3840 x 2160
Display (Display/Picture)
PQI (Picture Quality Index) - 3,100
Video Features
Picture Engine Q Engine | Motion Rate 200 | PQI (Picture Quality Index) 3100 | HDR (High Dynamic Range) QHDR 1500 | Q Contrast Yes | Dynamic Mega Contrast | Supreme UHD Dimming | Precision Black Pro | Q Colour
Audio Features
Dolby Digital Plus | DTS Codec | Sound Output (RMS) 40W | Speaker Type 4.2Ch | Woofer | Multiroom Link | Bluetooth Audio
Smart Service
Voice Interaction, Web Browser
Convergence
TV to Mobile - Mirroring , Mobile to TV - Mirroring, DLNA , 360 Video Player
Connectivity
HDMI 4 | USB 3


The Java Platform includes a powerful API for capturing, processing, and playing back audio and MIDI (Musical Instrument Digital Interface) data. This API is supported by an efficient sound engine which guarantees high-quality audio mixing and MIDI synthesis capabilities for the platform.
The provided reference implementation of this API supports the following features:
The above list describes the reference implementation, not the API itself. The API permits flexible configuration of the audio and MIDI system, including ways for applications to ask the system exactly what resources are installed and available.
javax.sound.sampled
Packagejavax.sound.midi
Packagejavax.sound.sampled.spi
Packagejavax.sound.midi.spi
Package


Ask questions about the core tech here, but not questions about prices or personal questions or GUI and please don't DM JL777.
https://dexstats.info/richlistlookup.php?address=RLVzC4tr9cNKvuw2z4m8KuMfZURwCehx55
https://medium.com/@jameslee777
100 messages
Before 05-Dec-19 12:00 AM
LocoMB27-Sep-19 11:16 AM
thanks!
I would sympathize with vi myself- I hate emacs
but you don't use a makefile?
I remember form once compiling an x server and having to do stuff in the makefile.. fells like in a Stephen King novel
Also, these low level tools need constant practice- I was sort of semi-proficient in vi, but that had totally decayed after like- a year or two..
jl777c27-Sep-19 11:20 AM
there is usually a makefile that already exists. add the new source files to the makefile and run make
usually i make a simple script file to issue all the commands to test a new iteration
so edit, save, run script, test, repeat
LocoMB27-Sep-19 11:22 AM
sounds good-
I guess those really evil makefiles are the ones that are made for multi-platform distributions
back in the day when Solaris BSD and all kind of competing unixoids were still a thing
Slyris29-Sep-19 05:51 PM
@LocoMB The current architecture of the Komodod make CLion really hard to use with it.

From my experience, I think that today when we think of a project from the beginning it is not a bad thing to think about those who use IDE's, you will not prevent those who want to use VI to do it.
On the other hand make a small local Makefile and supported only Linux, and think that everyone will use VI or create a script to compile, you lose the possible support of IDE's, one of my goals is to create a CMake for the Komodod project without breaking the backward compatibility with ZCash.
I can not for my part conceive of making a C++ project today without CLion, others it will be QTCreator, others it will be Visual Studio, other XCode, other emacs or VI. But the interest of CMake is that all its developers will enjoy their favorite editors/ide's.(edited)
Slyris29-Sep-19 05:58 PM
I can understand seeing some CMake dating from several years ago that we may be afraid to do, however as a modern CMake expert I think to provide a clean, easy to maintain and that will please to everyone.
Mihailo30-Sep-19 07:20 AM
Should we buy now
2
1
jl777c30-Sep-19 07:23 AM
7777.77 might be a good price
5
1
3
2
5
willofleo30-Sep-19 08:42 AM
all this binanace delisting must be good for atomic dex,
some large cap trading pair are being removed, I am sure they will seek new home, how do you think kmd atomic dex could go about taking advantage of this(edited)
jspook1603-Oct-19 02:30 PM
Offer free listing for a limited time? But we're still in beta so timing might be off
ohweoh03-Oct-19 02:56 PM
hey jl, why 777?
polycryptoblog03-Oct-19 03:02 PM
He reads writes and executes code
4
Oszy03-Oct-19 03:05 PM
his alias is rwxrwxrwx
farl04-Oct-19 07:35 AM
@ohweoh maybe he had the same diet as I have?
5
Slyris04-Oct-19 09:43 AM
@polycryptoblog Or he likes casino and the jackpot(edited)
Cryptoon04-Oct-19 10:38 AM
CrisF04-Oct-19 12:37 PM
Speaking of diet...
1
Cryptoon04-Oct-19 01:24 PM
So full of nutrients, so amazing and good for you
Slyris04-Oct-19 04:53 PM
lol
farl04-Oct-19 05:45 PM
Haha, good stuff. Now let James answer the real question: Why 777? chmod?
777 (seven hundred [and] seventy-seven) is the natural number following 776 and preceding 778. The number 777 is significant in numerous religious and political contexts.
LocoMB05-Oct-19 09:33 AM
one thing though: jl777 is without a doubt not chinese, because then it would be jl888, being most lucky number in China... no Chinese would settle for 777, ever!
*as opposed to poor silly Tschermany, where ist streng VERBOTEN, JA!, because it means HeilHilter (edited)
coingirl8705-Oct-19 09:39 AM
88 is not forbidden in germany
But everybody knows what 88 means or 18, 81....these are symbols of neonazis
Also hellyhansen
But its not forbidden ...because in germany we are free...we can say and think what we want
Thats a big benefit of germany against the rest of world
Acura05-Oct-19 09:54 AM
81 = Hells Angels (In germany)
coingirl8705-Oct-19 09:58 AM
Correct...but it combines both...neo nazi rocker
farl05-Oct-19 01:14 PM
Ok guys.  Farl are you ok? I can send you a granola bar. .
The news: According to a report in the Financial Times, a team of researchers from Google led by John Martinis have demonstrated quantum supremacy for the first time.
Komodo is pleased to announce the creation of Dilithium, a quantum secure blockchain. This technology is available to all within the Komodo ecosystem.
cascrypto11-Oct-19 07:29 AM
Thanks
phm8715-Oct-19 04:27 PM
Hello
We discussed with bitcoiners during meetups. Some were interested by komodo tech and dpow. Whitepaper was read but they are searching for the set of rules introduced by dpow. I linked few articles but they would like a list of rules such as https://hastebin.com/uladolizup.sql do we have such list ?
Thank you
jl777c15-Oct-19 04:32 PM
there are just 2 rules.
1. accept only notarizations that matches what your local node already has as its mainchain
2. if a new block arrives that tries to change a notarized block, reject it
phm8715-Oct-19 04:46 PM
Thank you. I sent the info to the person
vogelfreund8818-Oct-19 04:17 PM
K64 exit scam confirmed?
Markus18-Oct-19 04:22 PM
@vogelfreund88 I dont think this is a question to JL
1
Cryptoon18-Oct-19 04:57 PM
#talk-other-topics
игорь18-Oct-19 07:14 PM
What is your progress in integrating z-transactions into atomicDex?
jl777c18-Oct-19 07:28 PM
i am personally not doing that, the mm2 team is
I_R_Ben19-Oct-19 02:40 PM
@jl777c , I think you’ve got an impersonator unless you really are struggling with your usual exchange (edited)
ComputerGenie 👴👴👴19-Oct-19 02:46 PM
this looks like a job for @Moderator
2
CHMEX19-Oct-19 02:48 PM
faked account uses some special char after the c
I just got rid of him
7
4
Cryptoon19-Oct-19 04:28 PM
Jl using exchanges
ComputerGenie 👴👴👴19-Oct-19 04:32 PM
or searching for some rando "KMD holder"
mrlynch19-Oct-19 10:38 PM
lol, if these scammers would have half a brain they'd use someone else's name
@jl777c Any news on bringing atomic swap tech to other fields than crypto soon? For instance: swapping tickets for events or a 1-on-1 marketplace for placing sportsbets and sorts (1 taking action, 1 buying action at a certain price which are held by the atomic escrow tech and settled after the event took place). The last one is a multi billion (maybe trillion) business. I think in general adoption of the DEX will be much faster if you start bringing out usecase outside of crypto.
1
jl777c21-Oct-19 11:22 AM
if someone made a coin that represented these external things, then it would already work. it is up to others to launch such chains
PHBA206121-Oct-19 12:30 PM
the hard part is to enforce linkage between tokens & real world assets I think , and that is up to the laws/guidance/rules of companies/entities/countries
passcombo.com 🏴☠🏴21-Oct-19 04:03 PM
if I wanted to make memo-based message app with public content - which kind of blockchain is best for such? shall I start my own or I can use one existing ? fast blockspeed would be good
Oszy21-Oct-19 04:08 PM
as in z-tx memo ?
or mixed
passcombo.com 🏴☠🏴21-Oct-19 04:08 PM
more like t-tx memo(edited)
afaik zcash t-tx not allos memo
but btc deos
btc, bch, ltc ...
Im just thinking for more or less messanger app quick block speed is required like even maybe 5 seconds
Oszy21-Oct-19 04:10 PM
i am sure it's possible on an assetchain with custom options
passcombo.com 🏴☠🏴21-Oct-19 04:10 PM
1 sec would be perfect
another insane idea I was thinking if it is possible to have default preloaded addresses with small amounts for testing - to more easy allow users for "trying/testing" apps / crypto
so for example I would make some dust like 0.001 coin per address, at least in some early stage to increas adoption of the app
tha would also be usefull for test like beer pizza in the past - no need to ask anyone for change or search - you just create a wallet and in some misterious way same time "mine" some initial reaload available during first
N blocks
@Oszy so basically I should create my own chain to have required specs ? where can I learn how to do so and what is required for me to support it later on the go? I think those new invetions of nSPV and aPOW doulb be nice to, so that lite app is usable through nSPV and aPOW makes me not ti think about mining problems and overall blockchain problems
maybe for regular transparent chain nSPV is not so crucial
Just figure out what you need, apow is nice, or you can use verushash instead equihash, there are lots of options
passcombo.com 🏴☠🏴21-Oct-19 04:46 PM
"get KMD holders' addresses for airdrop" is not exactly what I asked, I was thinking more "someone download the app and opens wallet (create address) and get small amount of the coin - kind of reward supporting usage/adoption
there is nothing I found about memo in Antara framework though
@gcharang that looks simmilar to what Im thinking - twitter replacement - decentralized
and yes faucet sounds like it allows preloading addresses on demand
/on creation
Oszy21-Oct-19 05:14 PM
for that i believe you'd have to have a button in a gui, (if there's a gui) and a script that generates new address and pulls from faucet to the new address(edited)
passcombo.com 🏴☠🏴21-Oct-19 05:16 PM
yes basically wallet would be messanger app
while block explorers could work as web display of content, wallet (app with credits) would display personalized content(edited)
Oszy21-Oct-19 05:19 PM
i am thinking of a drawback of a public decentralized "twitter" style app, so what if there is like illegal content posted the kind that you should not even look at let alone having it associated with you ip ever?


public class Percentile extends AbstractUnivariateStatistic implements java.io.Serializable
There are several commonly used methods for estimating percentiles (a.k.a. quantiles) based on sample data. For large samples, the different methods agree closely, but when sample sizes are small, different methods will give significantly different results. The algorithm implemented here works as follows:
n
be the length of the (sorted) array and
0 < p <= 100
be the desired percentile. n = 1
return the unique array element (regardless of
the value of p
); otherwise pos = p * (n + 1) / 100
and the difference, d
between pos
and floor(pos)
(i.e. the fractional
part of pos
). If pos >= n
return the largest
element in the array; otherwiselower
be the element in position
floor(pos)
in the array and let upper
be the
next element in the array. Return lower + d * (upper - lower)
To compute percentiles, the data must be (totally) ordered. Input arrays
are copied and then sorted using Arrays.sort(double[])
.
The ordering used by Arrays.sort(double[])
is the one determined
by Double.compareTo(Double)
. This ordering makes
Double.NaN
larger than any other value (including
Double.POSITIVE_INFINITY
). Therefore, for example, the median
(50th percentile) of
{0, 1, 2, 3, 4, Double.NaN}
evaluates to 2.5.
Since percentile estimation usually involves interpolation between array
elements, arrays containing NaN
or infinite values will often
result in NaN
or infinite values returned.
Note that this implementation is not synchronized. If
multiple threads access an instance of this class concurrently, and at least
one of the threads invokes the increment()
or
clear()
method, it must be synchronized externally.
| Constructor and Description |
|---|
Percentile()
Constructs a Percentile with a default quantile
value of 50.0.
|
Percentile(double p)
Constructs a Percentile with the specific quantile value.
|
Percentile(Percentile original)
Copy constructor, creates a new
Percentile identical
to the original |
| Modifier and Type | Method and Description |
|---|---|
Percentile |
copy()
Returns a copy of the statistic with the same internal state.
|
static void |
copy(Percentile source,
Percentile dest)
Copies source to dest.
|
double |
evaluate(double[] values,
double p)
Returns an estimate of the
p th percentile of the values
in the values array. |
double |
evaluate(double[] values,
int start,
int length)
Returns an estimate of the
quantile th percentile of the
designated values in the values array. |
double |
evaluate(double[] values,
int begin,
int length,
double p)
Returns an estimate of the
p th percentile of the values
in the values array, starting with the element in (0-based)
position begin in the array and including length
values. |
double |
getQuantile()
Returns the value of the quantile field (determines what percentile is
computed when evaluate() is called with no quantile argument).
|
void |
setQuantile(double p)
Sets the value of the quantile field (determines what percentile is
computed when evaluate() is called with no quantile argument).
|
evaluate, test, test
public Percentile()
public Percentile(double p)
p
- the quantilejava.lang.IllegalArgumentException
- if p is not greater than 0 and less
than or equal to 100public Percentile(Percentile original)
Percentile
identical
to the original
original
- the Percentile
instance to copypublic double evaluate(double[] values, double p)
p
th percentile of the values
in the values
array.
Calls to this method do not modify the internal quantile
state of this statistic.
Double.NaN
if values
has length
0
p
) values[0]
if values
has length 1
IllegalArgumentException
if values
is null or p is not a valid quantile value (p must be greater than 0
and less than or equal to 100)
See Percentile
for a description of the percentile estimation
algorithm used.
values
- input array of valuesp
- the percentile value to computejava.lang.IllegalArgumentException
- if values
is null
or p is invalidpublic double evaluate(double[] values, int start, int length)
quantile
th percentile of the
designated values in the values
array. The quantile
estimated is determined by the quantile
property.
Double.NaN
if length = 0
quantile
)
values[begin]
if length = 1
IllegalArgumentException
if values
is null, or start
or length
is invalid
See Percentile
for a description of the percentile estimation
algorithm used.
evaluate
in interface UnivariateStatistic
evaluate
in class AbstractUnivariateStatistic
values
- the input arraystart
- index of the first array element to includelength
- the number of elements to includejava.lang.IllegalArgumentException
- if the parameters are not validpublic double evaluate(double[] values, int begin, int length, double p)
p
th percentile of the values
in the values
array, starting with the element in (0-based)
position begin
in the array and including length
values.
Calls to this method do not modify the internal quantile
state of this statistic.
Double.NaN
if length = 0
p
) values[begin]
if length = 1
IllegalArgumentException
if values
is null , begin
or length
is invalid, or
p
is not a valid quantile value (p must be greater than 0
and less than or equal to 100)
See Percentile
for a description of the percentile estimation
algorithm used.
values
- array of input valuesp
- the percentile to computebegin
- the first (0-based) element to include in the computationlength
- the number of array elements to includejava.lang.IllegalArgumentException
- if the parameters are not valid or the
input array is nullpublic double getQuantile()
public void setQuantile(double p)
p
- a value between 0 < p <= 100java.lang.IllegalArgumentException
- if p is not greater than 0 and less
than or equal to 100public Percentile copy()
copy
in interface UnivariateStatistic
copy
in class AbstractUnivariateStatistic
public static void copy(Percentile source, Percentile dest)
Neither source nor dest can be null.
source
- Percentile to copydest
- Percentile to copy tojava.lang.NullPointerException
- if either source or dest is null


Radwane Hassen
Welcome to bulshit academy, and buzzword world !
var requestStream = Rx.Observable.just('https://api.github.com/users');
var responseStream = requestStream
.flatMap(function(requestUrl) {
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
});
responseStream.subscribe(function(response) {
// render `response` to the DOM however you wish
});
/* Get stock data somehow */
var source = getStockData();
source
.filter(function (quote) {
return quote.price > 30;
})
.map(function (quote) {
return quote.price;
})
.forEach(function (price) {
console.log('Prices higher than $30: $' + price);
});
And there is more reactive library : baconjs, Rx.net... And Reactjs
Thinking in reactive : is changing to new paradigm, forget imperative and stateful habits of typical programming
render() {
return (
Checklist
{this.renderItems()}
);
Welcome to post Reactjs era


Javascript is disabled!
Javascript is disabled!
Sorry, this application requires
JavaScript
.
Please enable it in your web browser settings.


Innovate. Create. Win.
Read more
The team provides an interview with insights into the project.
Wireless Design and Development's web video series discusses the 2014 challenge results.


--- layout: post title: Early internet stuff date: 2004-07-28 00:00:00 category: personal ---
Steve Bowbrick has posted one of the original proposals for the Lloyds TSB student banking site.
If it's the same one I'm thinking of, when I was working for GT we took over the site from Webmedia and maintained it for a bit. It was one of the first bank sites I remember. Well, I say "remember": all that springs to mind is a load of student-oriented info and a camper van motif...


| The Metadata Community — Supporting Innovation in Metadata Design, Implementation & Best Practices | |||||||
Global navigation options: |
| Creator: | Mikael
Nilsson KMR Group, NADA, KTH (Royal Institute of Technology), Sweden Andy Powell Eduserv Foundation, UK Pete Johnston Eduserv Foundation, UK Ambjörn Naeve KMR Group, NADA, KTH (Royal Institute of Technology), Sweden |
|---|---|
| Date Issued: | 2008-01-14 |
| Identifier: | http://dublincore.org/documents/2008/01/14/dc-rdf/ |
| Replaces: | http://dublincore.org/documents/2007/06/04/dc-rdf/ |
| Replaces: | http://dublincore.org/documents/2002/07/31/dcmes-xml/ |
| Replaces: | http://dublincore.org/documents/2002/05/15/dcq-rdf-xml/ |
| Latest Version: | http://dublincore.org/documents/dc-rdf/ |
| Status of Document: | This is a DCMI Recommendation. |
| Description of Document: | This document provides recommendations for expressing Dublin Core metadata using RDF, the Resource Description Framework. |
References
Acknowledgements
Appendix A: Examples
This document provides recommendations for expressing DC metadata using RDF, the Resource Description Framework. It does this by describing how the features of the DCMI Abstract Model [ABSTRACT-MODEL] are represented using the RDF model (or abstract syntax), as defined by the RDF Concepts and Abstract Syntax specification [RDF-CONCEPTS]. It does not rely on any specific RDF syntax encoding, though examples using the RDF/XML Syntax Specification [RDF-SYNTAX-GRAMMAR] are provided in Appendix A. This allows Dublin Core metadata to be encoded using this specification in any RDF encoding syntax or other RDF representation system, such as RDF databases.
This Recommendation replaces the following DCMI document:
The document "Notes on DCMI specifications for Dublin Core metadata in RDF" [DC-RDF-NOTES] describes in more detail how this draft relates to the earlier specifications.
Many of the examples in this document make use of DCMI metadata terms [DCMI-TERMS]. See also the DCMI RDF Schemas for the DCMI terms [DCMI-SCHEMAS].
An RDF graph is a set of RDF triples
An RDF triple has three components:
an RDF subject, which is an RDF URI reference or a blank RDF node
an RDF predicate, which is an RDF URI reference
an RDF object, which is an RDF URI reference, a blank RDF node or an RDF literal
An RDF literal can be of two kinds:
an RDF plain literal is a character string with an optional associated language tag describing the language of the character string
We will use diagrams to illustrate RDF graphs (for namespace abbreviations, see Section 3). A simple triple may look like in the following figure:
| The structure of an RDF triple. In this figure, the RDF object is an RDF typed literal |
While a graph consisting of three triples may look like the following:
| An RDF graph consisting of three triples, connected via a blank RDF node. |
For further information on RDF, see the RDF Concepts and Abstract Syntax specification [RDF-CONCEPTS], the RDF Vocabulary Description Language [RDF-SCHEMA], and http://www.w3.org/RDF/.
| Namespace abbreviation | Full namespace URI |
|---|---|
dc |
http://purl.org/dc/elements/1.1/ |
dcterms |
http://purl.org/dc/terms/ |
dcam |
http://purl.org/dc/dcam/ |
rdf |
http://www.w3.org/1999/02/22-rdf-syntax-ns# |
xsd |
http://www.w3.org/2001/XMLSchema# |
ex |
http://www.example.org/ns# (an example
namespace) |
See also the DCMI RDF Schemas for the DCMI terms [DCMI-SCHEMAS].
This section describes how each of the constructs in the DCAM are represented in RDF. The RDF notions used here are defined in the RDF Concepts and Abstract Syntax specification [RDF-CONCEPTS] and the RDF Vocabulary Description Language [RDF-SCHEMA].
DCAM descriptions and resources are represented in the following way:
A DCAM statement is represented using an RDF triple comprising:
The following diagram illustrates the main features of the RDF representation of non-literal value surrogates.
| DC-TEXT representation | RDF graph |
|---|---|
@prefix dcterms: <http://purl.org/dc/terms/> . |
|
| The
representation of the DCAM
constructs in the case of a non-literal value surrogate. The notation "@en" represents an RDF language tag, while "^^ex:SubjectEncoding" represents an RDF Datatype. |
A DCAM value URI is represented using the RDF URI Reference of the value RDF node. If no value URI is given, the value RDF node is a blank node.
A DCAM vocabulary encoding scheme URI is represented using an RDF triple comprising:
an RDF subject that is the value RDF node.
an RDF predicate that is
the RDF URI reference dcam:memberOf
an RDF object with a corresponding RDF URI Reference being the DCAM vocabulary encoding scheme URI
A DCAM value string is represented using an RDF triple comprising:
an RDF subject that is the value RDF node
an RDF
predicate that is the RDF URI reference
rdf:value
an RDF
object that is an RDF Literal node
(either an RDF plain
literal or RDF
typed literal), containing
the DCAM value string.
A DCAM value string language is represented using a language tag associated with a RDF plain literal occurring as the RDF object of this RDF triple. The language tag is constructed as defined by RFC-3066, normalized to lowercase.
A DCAM syntax encoding scheme URI is represented using the RDF datatype URI associated with a RDF typed literal occurring as the RDF object of this RDF triple.
The following diagrams illustrate the main features of the RDF representation of literal value surrogates.
| DC-TEXT representation | RDF graph |
|---|---|
@prefix dcterms: <http://purl.org/dc/terms/> . |
|
| The
representation of the DCAM
constructs in the case of a literal value surrogate with a
language tag. The notation "@en" represents an RDF language tag. |
The following diagram illustrates the second case, using RDF typed literals:
| DC-TEXT representation | RDF graph |
|---|---|
@prefix xsd: <http://www.w3.org/2001/XMLSchema |
|
| The
representation of the DCAM
constructs in the case of a literal value surrogate with a
Syntax Encoding Scheme URI. The notation "^^xsd:int" represents an RDF Datatype. |
A DCAM description set is represented as
an RDF graph
that includes one or more DCAM descriptions as described above.
A DCAM value can be further described in a separate DCAM description
within the same DCAM description set.
This is represented in RDF by letting the value RDF node be the root of an
RDF
graph representing any DCAM statements in the DCAM description of the
value. Thus, the value RDF node
will be the RDF subject of a set of triples representing the DCAM
description of the value.
The RDF expression of the DCMI Abstract Model has a special status among the DCMI encoding specifications. As the semantics of the notions DCMI Abstract Model is based on the semantics of the corresponding notions in RDF (as defined by [RDF-SEMANTICS]), it is of fundamental importance that the RDF expression preserves any semantics of the DCAM. Also, any valid inferences that can be made using RDF semantics need to be valid when interpreted in terms of the DCMI Abstract Model. These requirements have not yet been formalized, but are thought to be reasonable and relatively straightforward. Among other things, formulating them would require defining a reverse mapping from RDF to the DCMI Abstract Model.
Using the range of the corresponding property. For example, if
the range of the property ex:owner
is ex:Person
,
it can be inferred that all values of the ex:owner
property are of type ex:Person
.
Using an explicit rdf:type
statement on the value.
For example, if a resource has the property rdf:type
with
the value ex:Person
, the value can be inferred to be of
the type ex:Person
.
ex:Book
,
even though this is not part of the metadata itself.It
is recommended that RDF applications use explicit rdf:type
triples, even if that means creating a separate DCAM description of
the value.
The property dcterms:type
has semantics very similar
to rdf:type
. At the time of writing, the precise
relationship between those properties remains undecided.
It is
recommended that RDF applications implementing this
specification primarily use and understand rdf:type
in
place of dcterms:type
when
expressing Dublin Core metadata in RDF, as most RDF processors come
with
built-in knowledge of rdf:type
.
Thanks to Tom Baker, the members of the DC Usage Board and the members of the DC Architecture Working Group for their comments on previous versions of this document.
The following examples use the DC-TEXT syntax [DC-TEXT] for describing examples of Dublin Core metadata. The corresponding RDF graph is then presented, using the RDF/XML syntax [RDF-SYNTAX-GRAMMAR]. Familiarity with the "striped" RDF/XML syntax is assumed. The W3C RDF Validator [RDF-VALIDATOR] service may be used to convert these RDF/XML samples to triples and graphs.
| Description | DC-TEXT representation | RDF/XML representation |
|---|---|---|
| A
description with a single statement, which uses a
value URI to identify the value. "The resource http://example.org/123 has the subject
identified by the URI http://example.org/taxonomy/D003.53 ." |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a
single value string and a vocabulary encoding scheme to describe the
value. "The resource http://example.org/123 has the subject
named 'Ornitology' from the Vocabulary Encoding Scheme http://example.org/taxonomy/MyVocab " |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a language-tagged
literal value. "The resource http://example.org/123 has the title
'Learning Biology' in english" |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a literal value with a
Syntax encoding scheme. "The resource http://example.org/person123 has the an age
of 43" |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses two
value strings, one language tagged and one using a syntax encoding
scheme, a vocabulary encoding scheme for the value and a value URI
identifying the value. "The resource http://example.org/123 has the subject from
the Vocabulary Encoding Scheme http://example.org/taxonomy/MyVocab
named 'Biology' in English and 'Biologi' in Swedish, which can be
represented using the string "EA32" according to the Syntax Encoding
Scheme http://example.org/taxonomy/SubjectEncoding , and
which is idenfified by the URI http://example.org/subject32 " |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a
single value string and a value URI,
together with a description of the value. The
description of the value has two statements, each of which only has a
value URI. "The resource http://example.org/123 has the creator
identified by http://example.org/person45 , represented by
the string "John Smith". The resource http://example.org/person45
is a person who has the phone number identified by tel:+358-555-1234567
(see RFC 3966)." |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a
value URI but no described resource URI. "The described resource has the subject identified by the URI http://example.org/taxonomy/D003.53 ." |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
| A
description with a single statement, which uses a
value string, but no value URI. The description of the value has no
described resource URI, but has two
statements, both of which use a
value URI. "The resource http://example.org/123 has a creator
represented by the string "John Smith". The creator is a person who
has the phone number identified by tel:+358-555-1234567
(see RFC 3966)." |
@prefix dcterms: <http://purl.org/dc/terms/> . |
<rdf:RDF xmlns:rdf=" |
Copyright © 1995-2014 DCMI. All Rights Reserved.


{% include "hr_partials/breadcrumb.html" ignore missing %}
{% include "hr_partials/key-metrics.html" ignore missing %}
{% include "hr_partials/side-menu.html" ignore missing %}
Responsibility level
| Vs 2014 |
Level |
Headcount |
| up 1.3% |
Senior Civil Servant |
4,850 |
| down 3.6% |
Grades 6 and 7 |
37,780 |
| up 0.3% |
Senior and Higher Executive Officers |
100,060 |
| up 4.4% |
Executive Officers |
115,600 |
| up 3.2% |
Administrative Officers and Assistants |
178,920 |
| down 7% |
Not Reported |
2,730 |
Skills & Expertise by department
| Department |
Top |
Gap |
| Department for International Development |
Project Management, Humanitarian response |
Diplomacy |
| Office for National Statistics |
Data analysis, Data standards |
Digital |
| Ministry of Justice |
Innovation, Legal |
Resourcing |
| Government Digital Service |
Agile, Digital |
Decision making |
| Foreign and Commonwealth Office |
Diplomacy, Communications |
Long term strategic planning |
Learning
Mentors
3,227
Civil Servants completing courses
156,470
{% endblock %}


This application allows you to create and spend from an Ethereum 2/3-multisig smart contract using your hardware wallet.
It was built by Unchained Capital to help holders worldwide safely store their ETH using multisig cold-storage. If you are storing ETH on a Trezor and you trust at least two other people, you could be doing it better. Now you can use this application with your trusted friends, family, and colleagues to protect your wealth.
To learn more about the design philosophy of this application and smart contract, read the blog post. If you are a developer you may want to check out the source code for the smart contract (which includes this dApp) on GitHub. Unchained Capital is also operating a bug bounty around this contract & dApp.
This application connects Trezor hardware wallets with the Ethereum blockchain.
When creating the multisig smart contract, 3 Trezors are required. When spending, 2/3 of these same Trezors are required. The private keys used to create and spend from a contract are only present on your Trezors.
This means that you are completely in control of your own security and accounting. In particular:
This application requires a funded account in a synced, connected Ethereum client to pay for gas.
The Ethereum transactions required to create and spend from the smart contract will be authored by this application. Broadcasting them to the Ethereum network requires a synced, connected Ethereum client. The client should have an account with some modest ETH balance to pay for gas. As of this writing, 0.01 ETH is more than sufficient.
The account used to pay for gas has absolutely no special rights to fund, spend from, or otherwise control the smart contract this application creates. Only the private keys on the 3 Trezor devices you used to create the smart contract matter. Creating and spending from a smart contract can be done by totally separate accounts, as long as this application and the same 3 Trezors are used.
Because of this design, a browser-based wallet such as Metamask provides acceptable security and is also extremely convenient.
Full Ethereum nodes such as Parity or Geth will also work, though may require some special configuration or browser extensions.
Get more details about connecting to an Ethereum client in
the dApp section of the README
for this
GitHub repo.
Unchained Capital is actively developing this project and very much welcomes feedback. To file bugs or request features, please use GitHub issues.
Unchained Capital is also operating a bug bounty for this project.
The source code of the smart contract used by this version of this application is below. You can also find it on GitHub or see it on Etherscan for any contract created by this application.
pragma solidity ^0.4.19;
// A 2/3 multisig contract which is compatible with Trezor-signed messages.
//
// To authorize a spend, two signtures must be provided by 2 of the 3 owners.
// To generate the message to be signed, provide the destination address and
// spend amount (in wei) to the generateMessageToSignmethod.
// The signatures must be provided as the (v, r, s) hex-encoded coordinates.
// The S coordinate must be 0x00 or 0x01 corresponding to 0x1b and 0x1c, respectively.
// See the test file for example inputs.
//
// If you use other software than the provided dApp or scripts to sign the message,
// verify that the message shown by the trezor device matches the generated message in hex.
//
// WARNING: The generated message is only valid until the next spend is executed.
// after that, a new message will need to be calculated.
//
// WARNING: The signing algorithm Trezor uses is different than that
// of Ledger, Geth, Etc. This contract is for Trezor managed private
// keys ONLY.
//
// ADDITIONAL WARNING: This contract is **NOT** ERC20 compatible.
// Tokens sent to this contract will be lost forever.
//
contract TrezorMultiSig2of3 {
// The 3 addresses which control the funds in this contract. The
// owners of 2 of these addresses will need to both sign a message
// allowing the funds in this contract to be spent.
mapping(address => bool) private owners;
// The contract nonce is not accessible to the contract so we
// implement a nonce-like variable for replay protection.
uint256 public spendNonce = 0;
// Contract Versioning
uint256 public unchainedMultisigVersionMajor = 1;
uint256 public unchainedMultisigVersionMinor = 0;
// An event sent when funds are received.
event Funded(uint new_balance);
// An event sent when a spend is triggered to the given address.
event Spent(address to, uint transfer);
// Instantiate a new Trezor Multisig 2 of 3 contract owned by the
// three given addresses
function TrezorMultiSig2of3(address owner1, address owner2, address owner3) public {
address zeroAddress = 0x0;
require(owner1 != zeroAddress);
require(owner2 != zeroAddress);
require(owner3 != zeroAddress);
require(owner1 != owner2);
require(owner2 != owner3);
require(owner1 != owner3);
owners[owner1] = true;
owners[owner2] = true;
owners[owner3] = true;
}
// The fallback function for this contract.
function() public payable {
Funded(this.balance);
}
// Generates the message to sign given the output destination address and amount.
// includes this contract's address and a nonce for replay protection.
// One option to independently verify: https://leventozturk.com/engineering/sha3/ and select keccak
function generateMessageToSign(address destination, uint256 value) public constant returns (bytes32) {
require(destination != address(this));
bytes32 message = keccak256(spendNonce, this, value, destination);
return message;
}
// Send the given amount of ETH to the given destination using
// the two triplets (v1, r1, s1) and (v2, r2, s2) as signatures.
// s1 and s2 should be 0x00 or 0x01 corresponding to 0x1b and 0x1c respectively.
function spend(address destination, uint256 value, uint8 v1, bytes32 r1, bytes32 s1, uint8 v2, bytes32 r2, bytes32 s2) public {
// This require is handled by generateMessageToSign()
// require(destination != address(this));
require(this.balance >= value);
require(_validSignature(destination, value, v1, r1, s1, v2, r2, s2));
spendNonce = spendNonce + 1;
destination.transfer(value);
Spent(destination, value);
}
// Confirm that the two signature triplets (v1, r1, s1) and (v2, r2, s2)
// both authorize a spend of this contract's funds to the given
// destination address.
function _validSignature(address destination, uint256 value, uint8 v1, bytes32 r1, bytes32 s1, uint8 v2, bytes32 r2, bytes32 s2) private constant returns (bool) {
bytes32 message = _messageToRecover(destination, value);
address addr1 = ecrecover(message, v1+27, r1, s1);
address addr2 = ecrecover(message, v2+27, r2, s2);
require(_distinctOwners(addr1, addr2));
return true;
}
// Generate the the unsigned message (in bytes32) that each owner's
// Trezor would have signed for the given destination and amount.
//
// The generated message from generateMessageToSign is converted to
// ascii when signed by a trezor.
//
// The required Trezor signing prefix, the length of this
// unsigned message, and the unsigned ascii message itself are
// then concatenated and hashed with keccak256.
function _messageToRecover(address destination, uint256 value) private constant returns (bytes32) {
bytes32 hashedUnsignedMessage = generateMessageToSign(destination, value);
bytes memory unsignedMessageBytes = _hashToAscii(hashedUnsignedMessage);
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix,bytes1(unsignedMessageBytes.length),unsignedMessageBytes);
}
// Confirm the pair of addresses as two distinct owners of this contract.
function _distinctOwners(address addr1, address addr2) private constant returns (bool) {
// Check that both addresses are different
require(addr1 != addr2);
// Check that both addresses are owners
require(owners[addr1]);
require(owners[addr2]);
return true;
}
// Construct the byte representation of the ascii-encoded
// hashed message written in hex.
function _hashToAscii(bytes32 hash) private pure returns (bytes) {
bytes memory s = new bytes(64);
for (uint i = 0; i < 32; i++) {
byte b = hash[i];
byte hi = byte(uint8(b) / 16);
byte lo = byte(uint8(b) - 16 * uint8(hi));
s[2*i] = _char(hi);
s[2*i+1] = _char(lo);
}
return s;
}
// Convert from byte to ASCII of 0-f
// http://www.unicode.org/charts/PDF/U0000.pdf
function _char(byte b) private pure returns (byte c) {
if (b < 10) return byte(uint8(b) + 0x30);
else return byte(uint8(b) + 0x57);
}
}
This application is in “alpha” state and is presented for evaluation and testing only. It is provided “as is,” and any express or implied warranties, including but not limited to the implied warranties of merchantability and fitness for a particular purpose, are disclaimed. By using this application, you accept all risks of such use, including full responsibility for any direct or indirect loss of any kind resulting from the use of this application, which may involve complete loss of any ETH or other coins associated with addresses used with this application. In no event shall Unchained Capital, Inc., its employees and affiliates, or developers of this application be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this application, even if advised of the possibility of such damage.


The Mind
Start a Game
Start a new game
Link to that game:
Join a game
To join an existing game, get someone to send you a link to the game and join directly via the link.


:(
Something went wrong!
We're currently in beta stage so we cannot tell you what might have caused it to happen.
Make sure that you've entered the current information in case you've provided us some details.
Please try again.


Python is an amazing language to learn.
We all should be learning it.
One of the cool usecase for python is sending email
You could use the power of python to spam somebody or build your new business
With great power comes great responsibility. Use it wisely.


ST MARGARETS
£249,950
Due to an oversight in the Local Community Act of 1856, permission has been granted for a single storey dwelling to be built on the paved area at No.s 109-111 St Margarets Road. The dwelling will be situated outside Sunshine & Ravioli and Frisby Butchers. The property has already been let to a Mr.S.Claus who intends to allow the children of St Margarets to visit on the evening of Friday 9th December and during the day on Saturdays 10th and 17th December.
Chase Buchanan is sponsoring Santa's accommodation and we thank them for their continued support of local community events.