library(DBI)
library(rlang)
library(httr)
library(RPostgres)
<- function(url = Sys.getenv("DATA_WAREHOUSE_URL")) {
connect_to_dwh if (url == "") abort("You must specify a dwh URL.")
check_installed(pkg = "httr")
check_installed(pkg = "RPostgres")
<- parse_url(url)
db_params
<- Postgres()
db_drv <- db_params$username
db_user <- db_params$password
db_password <- db_params$hostname
db_host <- db_params$port %||% 5432
db_port <- db_params$path
db_name
dbConnect(
db_drv,dbname = db_name,
host = db_host,
port = db_port,
user = db_user,
password = db_password
) }
Writing Internal Libraries for Analytics Work
Or packages, or modules, or whatever you wish to call them
Introduction
By definition, library code is code that’s written to being reused by programs other than itself that are unrelated to each other. For instance, dplyr
(R) and pandas
(Python) are common examples of library code: Instead of writing code from scratch to work with tabular data, you might use one of those two fantastic libraries. And you get some additional benefits from using them:
- Those libraries are well-documented, so it’s easy to figure out how to use them.
- They’re well-tested, so you (presumably) know that bugs are less likely than if you were to try to write the same functionality from scratch.
- They’re (relatively) performant.
- They’re widely used, so it’s easy to find answers to questions and get help from the communities using them.
A Common Library
At CollegeVine, we have collegeviner
: An R package containing a lot of code that we use very often for all kinds of analytics projects. Some things that live in collegeviner
include:
- Plot theming code, so that we can consistently theme graphics across all of our work.
- A custom implementation of item-based collaborative filtering, which is core to our school recommendation system.
DBI
andaws.s3
wrappers for connecting to and querying our databases and working with data in S3.- Helper methods for common math we do, such as converting between odds, log-odds, and probabilities.
- Miscellaneous helper code for things that don’t exist natively in R, such as
yeet
for removing an item from a list and%notin%
, the inverse of the%in%
operator. - An implementation of the Brier Skill Score, which is a metric we often use for evaluating classification models.
- A lot more!
You might think of collegeviner
as being a common library of things that our team does often, so we don’t need to repeat ourselves or reinvent the wheel.
A Toy Example
Let’s imagine that you’re setting up a common library (in this example, an R package) for your team. The first thing you might want to do is have some logic to help your team connect to your data warehouse. For this example, let’s just imagine that “warehouse” is your local Postgres instance. Then, you might write a method for your library called connect_to_dwh
like this:
Now you have a single function that your whole team can share to connect to your data warehouse, assuming that they can provide the connection string. Let’s test out how the workflow might look for querying data now.
Connecting
Sys.setenv(DATA_WAREHOUSE_URL = "postgresql://localhost:5432/postgres")
<- connect_to_dwh() conn
And that’s it! You’re connected. You can now query away using dbGetQuery()
, a custom wrapper, dbplyr
, or any other method of choice.
Querying
## Put some data into the warehouse for example purposes
dbWriteTable(conn, Id(schema = "blog", table = "iris"), janitor::clean_names(iris))
<- dbGetQuery(
result conn = conn,
"
SELECT species, MAX(sepal_length) AS max_sepal_length
FROM blog.iris
GROUP BY species
ORDER BY 2 DESC
"
)
pretty_print(result)
| species | max_sepal_length |
|---|---|
| virginica | 7.9 |
| versicolor | 7.0 |
| setosa | 5.8 |
Testing
It’s also important to test your code. testthat
makes writing unit tests for your new connect_to_dwh
function very simple.
library(testthat)
test_that("Connecting works as expected", {
## This should error because the URL is empty
expect_error(
connect_to_dwh(""),
"You must specify a dwh URL"
)
<- connect_to_dwh()
conn
## Should return a PqConnection object
expect_s4_class(conn, "PqConnection")
## Should be able to query an example table
expect_equal(
dbGetQuery(conn, "SELECT COUNT(*) FROM blog.iris")$count,
150
) })
Test passed 🎉
Versioning
Lastly, it’s important to version your code. Semantic Versioning (SemVer) is a very common standard for versioning library code. In R specifically, you can read about versioning in Chapter 22 of R Packages.
 Incrementing your package’s version shows your teammates that something has changed in your library, and they can update their code to rely on the latest version (if they wish), or continue using the current version they’re on, or anything else.
One Library Per Model
In addition to a common library for sharing code that’s very often used across the data org, our team has also gotten into the habit of having a library per ML model in production. This definition can be a bit flexible (both in terms of what “ML model” means, and also what “production” means), but the basic principle should be the same: ML in production requires at least some training logic and some monitoring logic. It’s a good idea to share code between those two things. Let’s consider another simple example.
Iris Species Prediction
Let’s imagine that we work for a florist. On our website, we have a service where someone can provide some measurements about an iris (either a setosa or a virginica), as we’ll tell them which of the two we think it is. We know we’ll want to retrain the model periodically as we get more data, and we’ll also want to monitor how our model performs out-of-sample. Both training the model and monitoring will require some shared logic: loading raw data, doing feature engineering, and making predictions. So it would make sense to have those two jobs rely on a single library, as opposed to needing to repeat the logic. Let’s write that library here.
Fetching the Data
First, let’s write a method to fetch the raw data from our data warehouse. In practice, it probably makes sense to factor out the SQL here into individual SQL scripts, but for this example I’ll just include the SQL directly as a string.
<- function(conn) {
fetch_raw_data dbGetQuery(
conn = conn,
"
SELECT *
FROM blog.iris
WHERE species IN ('setosa', 'virginica')
"
) }
Feature Engineering
Next, let’s write some methods to create features.
<- function(sepal_length) {
create_sepal_length_feature + rnorm(n = length(sepal_length))
sepal_length
}
<- function(petal_width) {
create_petal_width_feature + rgamma(n = length(petal_width), shape = 2)
petal_width }
And then we can write a function to take our raw data, run the feature engineering steps, and return the features.
<- function(raw_data) {
create_features <- create_sepal_length_feature(raw_data$sepal_length)
sepal_length <- create_petal_width_feature(raw_data$petal_width)
petal_width <- raw_data$species == "setosa"
is_setosa
data.frame(
sepal_length,
petal_width,
is_setosa
) }
Model Fitting and Prediction
Next, let’s write methods to fit the model and make predictions.
<- function(features) {
fit_model <- is_setosa ~ sepal_length + petal_width
formula
## Dynamically extract the variables in the formula
## so we don't need to repeat ourselves
<- as.character(labels(terms(formula)))
predictors <- as.character(formula[[2]])
target
## Very basic error handling
if (!all(c(predictors, target) %in% colnames(features))) {
abort("Some required columns were missing from `features`")
}
<- glm(
model
formula,data = features,
family = binomial
)
class(model) <- c("irises", class(model))
model
}
<- function(object, newdata = NULL, ...) {
predict.irises <- predict.glm(
probs
object,
newdata,type = "response"
)
## If the predicted probability is > 50%,
## return `true`, else return `false`
> 0.50
probs }
Model Evaluation
And finally, let’s add a function to compute the model’s accuracy on some evaluation data.
<- function(prediction, is_setosa) {
compute_accuracy 100 * sum(prediction == is_setosa) / length(prediction)
}
Testing
It’s important to note that all of the methods above can and should be unit tested in the same way we tested our helper for connecting to the database. Testing is a great way to ensure the correctness of your code and make it more maintainable by making it easier to refactor in the future, and putting all of your modeling logic into a library like this makes it very easy to test. For instance, here’s how you might write a couple of unit tests for the petal width feature.
test_that("Petal width feature is created correctly", {
## The feature should be positive even when the
## petal width is zero, since we're adding gamma
## random noise.
expect_gt(create_petal_width_feature(0), 0)
## It should be extremely unlikely that a single
## draw from a gamma(2) is >10, which means this
## feature should be < 10 when the input is 0 in
## the vast majority of cases.
##
## NOTE: This is by definition a brittle test, and
## I wouldn't recommend writing tests that are
## probabilistic like this in practice unless
## you really need to. If you do, this will
## fail _some_ of the time, at random, even
## if "some" is a very small percentage.
::walk(
purrrrep(0, 100),
function(x) {
expect_lt(
create_petal_width_feature(x),
10
)
}
) })
Test passed 🥇
A Retraining Job
Great! Now that we have all of that library code written, we can package it up into a retraining job. A very simple training job might look like this:
First, connect to the data warehouse
<- connect_to_dwh() conn
Next, fetch the raw data from the warehouse that we need to train the model.
<- fetch_raw_data(conn)
raw
pretty_print(head(raw))
| sepal_length | sepal_width | petal_length | petal_width | species |
|---|---|---|---|---|
| 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 5.4 | 3.9 | 1.7 | 0.4 | setosa |
Next, create the features from the raw data by running the feature engineering pipeline.
<- create_features(raw)
features
pretty_print(head(features))
| sepal_length | petal_width | is_setosa |
|---|---|---|
| 3.418 | 2.724 | TRUE |
| 5.585 | 2.579 | TRUE |
| 4.362 | 0.979 | TRUE |
| 4.587 | 1.677 | TRUE |
| 3.476 | 2.926 | TRUE |
| 4.282 | 2.732 | TRUE |
Then fit a model using the features.
<- fit_model(features)
model
pretty_print(coef(model))
| x | |
|---|---|
| (Intercept) | 11.167 |
| sepal_length | -1.564 |
| petal_width | -0.674 |
Finally, evaluate the performance of the model by making predictions and computing the accuracy of those predictions.
<- predict(model)
preds <- compute_accuracy(preds, features$is_setosa)
accuracy
cat(paste0("Model accuracy is ", accuracy, "%"))
Model accuracy is 87%
And that’s it – you have a simple retraining job. This is a very minimal example, but this general framework is very flexible and modular, and it makes up the foundation for how we write our retraining jobs at CollegeVine. You can plug and play all different kinds of feature engineering logic, logic to fetch raw data, metrics, etc. We also use MLFlow for versioning models and tracking experiments, so our retraining jobs have lots of logging of artifacts, parameters, and metrics to our MLFlow instance.
A Monitoring Job
Next, let’s imagine we want to monitor out-of-sample performance of the model. Let’s modify the table with our raw data in the database for this, just for the sake of an example.
<- dbWithTransaction(
transaction_result conn = conn,
{dbExecute(
conn = conn,
"
ALTER TABLE blog.iris
ADD COLUMN created_at TIMESTAMP
"
)
dbExecute(
conn = conn,
"
UPDATE blog.iris
SET created_at = NOW() - random() * INTERVAL '2 weeks'
"
)
} )
Great, and now let’s make one or two small modifications to our code from above that pulled the raw data from the data warehouse.
<- function(conn, created_after = '1970-01-01 00:00:00') {
fetch_raw_data dbGetQuery(
conn = conn,
sprintf(
"
SELECT *
FROM blog.iris
WHERE
species IN ('setosa', 'virginica')
AND created_at > '%s'
",
created_after
)
) }
All we’ve done here is added the ability to specify a created_at
date to use as the cutoff point, where we’d only include records in our raw data that were created after said point. In practice, this lets us filter our raw data down to only records that were created after the model was trained (the out-of-sample data).
## In practice, this would be set at training time and "frozen"
## possibly by logging the value as a parameter in the MLFlow run
<- median(fetch_raw_data(conn)$created_at) model_trained_at
And now that we’ve artificially created a trained_at
date for the model, we can run our monitoring job. It’s quite simple, and very similar to the retraining job. All we do here is pull raw data that has been created since the model was trained, run the feature engineering pipeline, make predictions, and compute the accuracy of the model out-of-sample.
<- fetch_raw_data(conn, created_after = model_trained_at)
raw
<- create_features(raw)
features <- predict(model, features)
predictions
<- compute_accuracy(predictions, features$is_setosa)
accuracy
cat(paste0("Out-of-sample accuracy is ", accuracy, "%"))
Out-of-sample accuracy is 82%
Tying it Together
The key piece to notice is how much we’re leveraging our library code in both the retraining and monitoring job. In both cases, we’re doing some very similar things – pulling raw data, creating features, making predictions, computing accuracy – so it makes a lot of sense that we’d want to reuse the code for those two jobs.
There might also be more use cases for the code: More retraining or monitoring jobs, REST APIs, ETL jobs, etc. The more times you need to rely on the same logic, the more benefit you’ll derive from having a single source of truth for all of the logic for your modeling process.
It also might be useful to separate this library from the common library proposed at the start. There are important tradeoffs to consider: On one hand, a single library might be convenient for having all of your logic in a single place. But on the other hand, as your library grows in scope, it’ll necessarily have a bigger footprint, rely on more dependencies, etc. which will make its use and maintenance more difficult. A happy middle ground for us has been having a single library per “model” or use case. For instance, at CollegeVine we have a package called mlchancing
for our chancing model and a separate package called schoolrecommendr
for school recommendations and affinity scoring. Keeping these separate has made it easier to iterate on each model individually while also not being a maintenance or ramp-up headache.
It’s my view that models and other analytics work that is in production is software, and should be treated as such. If a model is going to be shipped to production, it at the very least needs to be tested, documented, versioned, and put through some kind of CI/CD process. It’d be even better if it’s monitored automatically so that the data scientists working on it can be notified quickly if things start going wrong. Ultimately, writing library code for your modeling work is very well-suited to meeting all of these expectations. And it also just makes everyone’s lives easier by not needing to reinvent the wheel all the time.


-
-
Andrew Bud of mBlox on flat-rate data in the short and medium-term for mobile telcos
-
Not sure I agree: in a capitalistic society anything done is (technically) market-driven. I like the idea of ad-funding coming to mobile, but it's a model transplanted from the fixed internet, which had no micropayment mechanism (i.e. PSMS) from day 1.
-
-
-
Consensual hallucinations and project management
-
-
-
-
-
"Gianic says it's also important to provide some fast, if minor, successes to help rebuild team morale. "Identify some quick wins to help the team feel the project is getting back on track""
-
"Will there be a time when it's no longer possible to have a very separate work and home life in our mobile/web ten point seven and a half world?". I think some of us are already there...
-
-
Lovely
-
-
Excellent survey. These guys have a fantastic product, making the previously impossible, possible :)
-
"it’s going to attract a hell of a lot of competition from people who you didn’t have to compete with before... Frequently while you’re still laughing about how horribly they’re going to fail when they realize how difficult your industry is. "
-
"Any intelligent fool can make things bigger, more complex and more violent. It takes a touch of genius and a lot of courage to move in the opposite direction"


WITNESS LIST Veteran Affairs & Military Installations Committee February 19, 2003 - 1:30P Defense Issues & Base Realignment and Closure ON: Perez, Ed Executive Director (Texas Office of State-Federal Relations) Mobilization and Activation of Texas Nat'l. Guard ON: Dehnert, Allen Assistant Adjutant General (Adjutant General's Department) Goodwin, Bill Assistant Adjutant General (Texas National Guard) Marty, Wayne D. Adjutant General (Texas National Guard) Texas Veterans Commission Info. & Budget Request ON: Duncan, Jim Chairman (Texas Veterans Commission) Nier, James E. Executive Director (Texas Veterans Commission)


public final class SegmentInfos extends Object implements Cloneable , Iterable < SegmentInfo >
| Modifier and Type | Class and Description |
|---|---|
static class
|
SegmentInfos.FindSegmentsFile
Utility class for executing code that needs to do
something with the current segments file.
|
| Modifier and Type | Field and Description |
|---|---|
int
|
counter
|
static int
|
CURRENT_FORMAT
|
static int
|
FORMAT
The file format version, a negative number.
|
static int
|
FORMAT_3_1
Each segment records the Lucene version that created it.
|
static int
|
FORMAT_CHECKSUM
This format adds a checksum at the end of the file to
ensure all bytes were successfully written.
|
static int
|
FORMAT_DEL_COUNT
This format adds the deletion count for each segment.
|
static int
|
FORMAT_DIAGNOSTICS
This format adds optional per-segment String
diagnostics storage, and switches userData to Map
|
static int
|
FORMAT_HAS_PROX
This format adds the boolean hasProx to record if any
fields in the segment store prox information (ie, have
omitTermFreqAndPositions==false)
|
static int
|
FORMAT_HAS_VECTORS
Each segment records whether it has term vectors
|
static int
|
FORMAT_LOCKLESS
This format adds details used for lockless commits.
|
static int
|
FORMAT_MAXIMUM
|
static int
|
FORMAT_MINIMUM
|
static int
|
FORMAT_SHARED_DOC_STORE
This format allows multiple segments to share a single
vectors and stored fields file.
|
static int
|
FORMAT_SINGLE_NORM_FILE
This format adds a "hasSingleNormFile" flag into each segment info.
|
static int
|
FORMAT_USER_DATA
This format adds optional commit userData (String) storage.
|
| Constructor and Description |
|---|
SegmentInfos
()
|
| Modifier and Type | Method and Description |
|---|---|
void
|
add
(
SegmentInfo
si)
|
void
|
addAll
(
Iterable
<
SegmentInfo
> sis)
|
List
<
SegmentInfo
>
|
asList
()
Returns all contained segments as an
unmodifiable
List
view.
|
Set
<
SegmentInfo
>
|
asSet
()
Returns all contained segments as an
unmodifiable
Set
view.
|
void
|
changed
()
Call this before committing if changes have been made to the
segments.
|
void
|
clear
()
|
Object
|
clone
()
Returns a copy of this instance, also copying each
SegmentInfo.
|
boolean
|
contains
(
SegmentInfo
si)
|
Collection
<
String
>
|
files
(
Directory
dir,
boolean includeSegmentsFile)
Returns all file names referenced by SegmentInfo
instances matching the provided Directory (ie files
associated with any "external" segments are skipped).
|
static long
|
generationFromSegmentsFileName
(
String
fileName)
Parse the generation off the segments file name and
return it.
|
static int
|
getDefaultGenLookahedCount
()
|
int
|
getFormat
()
|
long
|
getGeneration
()
|
static
PrintStream
|
getInfoStream
()
|
static long
|
getLastCommitGeneration
(
Directory
directory)
Get the generation of the most recent commit to the
index in this directory (N in the segments_N file).
|
static long
|
getLastCommitGeneration
(
String
[] files)
Get the generation of the most recent commit to the
list of index files (N in the segments_N file).
|
static
String
|
getLastCommitSegmentsFileName
(
Directory
directory)
Get the filename of the segments_N file for the most
recent commit to the index in this Directory.
|
static
String
|
getLastCommitSegmentsFileName
(
String
[] files)
Get the filename of the segments_N file for the most
recent commit in the list of index files.
|
long
|
getLastGeneration
()
|
String
|
getNextSegmentFileName
()
Get the next segments_N filename that will be written.
|
String
|
getSegmentsFileName
()
Get the segments_N filename in use by this segment infos.
|
Map
<
String
,
String
>
|
getUserData
()
|
long
|
getVersion
()
version number when this SegmentInfos was generated.
|
int
|
indexOf
(
SegmentInfo
si)
|
SegmentInfo
|
info
(int i)
|
Iterator
<
SegmentInfo
>
|
iterator
()
Returns an
unmodifiable
Iterator
of contained segments in order.
|
void
|
pruneDeletedSegments
()
Prunes any segment whose docs are all deleted.
|
SegmentInfos
|
range
(int first,
int last)
Deprecated.
use
asList().subList(first, last)
instead.
|
void
|
read
(
Directory
directory)
This version of read uses the retry logic (for lock-less
commits) to find the right segments file to load.
|
void
|
read
(
Directory
directory,
String
segmentFileName)
Read a particular segmentFileName.
|
static long
|
readCurrentVersion
(
Directory
directory)
Deprecated.
Load the SegmentInfos and then call
getVersion()
.
|
void
|
remove
(int index)
|
void
|
remove
(
SegmentInfo
si)
|
static void
|
setDefaultGenLookaheadCount
(int count)
Advanced: set how many times to try incrementing the
gen when loading the segments file.
|
void
|
setFormat
(int format)
|
static void
|
setInfoStream
(
PrintStream
infoStream)
If non-null, information about retries when loading
the segments file will be printed to this.
|
int
|
size
()
|
String
|
toString
(
Directory
directory)
|
int
|
totalDocCount
()
Returns sum of all segment's docCounts.
|
public static final int FORMAT
public static final int FORMAT_LOCKLESS
public static final int FORMAT_SINGLE_NORM_FILE
public static final int FORMAT_SHARED_DOC_STORE
public static final int FORMAT_CHECKSUM
public static final int FORMAT_DEL_COUNT
public static final int FORMAT_HAS_PROX
public static final int FORMAT_USER_DATA
public static final int FORMAT_DIAGNOSTICS
public static final int FORMAT_HAS_VECTORS
public static final int FORMAT_3_1
public static final int CURRENT_FORMAT
public static final int FORMAT_MINIMUM
public static final int FORMAT_MAXIMUM
public int counter
public void setFormat(int format)
public int getFormat()
public SegmentInfo info(int i)
public static long getLastCommitGeneration( String [] files)
files
- -- array of file names to check
public static long getLastCommitGeneration( Directory directory) throws IOException
directory
- -- directory to search for the latest segments_N file
IOException
public static String getLastCommitSegmentsFileName( String [] files) throws IOException
files
- -- array of file names to check
IOException
public static String getLastCommitSegmentsFileName( Directory directory) throws IOException
directory
- -- directory to search for the latest segments_N file
IOException
public String getSegmentsFileName()
public static long generationFromSegmentsFileName( String fileName)
public String getNextSegmentFileName()
public final void read( Directory directory, String segmentFileName) throws CorruptIndexException , IOException
directory
- -- directory containing the segments file
segmentFileName
- -- segment file to load
CorruptIndexException
- if the index is corrupt
IOException
- if there is a low-level IO error
public final void read( Directory directory) throws CorruptIndexException , IOException
CorruptIndexException
- if the index is corrupt
IOException
- if there is a low-level IO error
public void pruneDeletedSegments() throws IOException
IOException
public Object clone()
public long getVersion()
public long getGeneration()
public long getLastGeneration()
@Deprecated public static long readCurrentVersion( Directory directory) throws CorruptIndexException , IOException
getVersion()
.
CorruptIndexException
- if the index is corrupt
IOException
- if there is a low-level IO error
public static void setInfoStream( PrintStream infoStream)
public static void setDefaultGenLookaheadCount(int count)
public static int getDefaultGenLookahedCount()
setDefaultGenLookaheadCount(int)
public static PrintStream getInfoStream()
setInfoStream(java.io.PrintStream)
@Deprecated public SegmentInfos range(int first, int last)
asList().subList(first, last)
instead.
public Collection < String > files( Directory dir, boolean includeSegmentsFile) throws IOException
IOException
public int totalDocCount()
public void changed()
public Iterator < SegmentInfo > iterator()
Iterator
of contained segments in order.
iterator
in interface
Iterable
<
SegmentInfo
>
public List < SegmentInfo > asList()
List
view.
public Set < SegmentInfo > asSet()
Set
view.
The iterator is not sorted, use
List
view or
iterator()
to get all segments in order.
public int size()
public void add( SegmentInfo si)
public void addAll( Iterable < SegmentInfo > sis)
public void clear()
public void remove( SegmentInfo si)
public void remove(int index)
public boolean contains( SegmentInfo si)
public int indexOf( SegmentInfo si)


(W)BP#3 - HAProxy SNI, IPython, PostgreSQL and VIM
A new bucket post - I will change them from weekly to "whenever I feel like it". Mainly because I can't find the time to write actual posts between the bucket posts and I don't want this blog to consist solely of bucket posts.
SSL Client Certificate Support for Owncloud - Meanwhile on the interwebs, the support for client certificate authentication in Owncloud's desktop client "Mirall" is progressing. So I didn't do anything and I didn't learn anything... why is this even here?
Because I'm really looking forward to it! In fact, I'm planning on writing a blog post about the lack of support for additional authentication layers in desktop applications next week!
Also, I'm curious who will claim my the bounty! I assume @qknight.
Windows NTP Problems Round 2 - Apparently my "fix" from last weeks post didn't really fix my time issue with Windows 8. After a reboot, the clock is automatically set be off by one hour. Fortunately a friend of mine read the post and send me this link.
Dual Boot: Fix Time Differences Between Ubuntu And Windows
The problem lies in my dual boot setup of Kubuntu 14.04 and Windows 8.1. For me the solution was this command.
sudo sed -i 's/UTC=yes/UTC=no/' /etc/default/rcS
If you want to fix the problem using Windows, checkout the link above. There is more then one way to do this.
SNI with HAProxy - Last week I encountered a few problems with HAProxy and Server Name Indication, or SNI.
SNI is used by webservers, to distinguish between multiple SSL/TLS vhosts. In a normal HTTP setup, webservers can easily tell which site is requested. When TLS is in place, this becomes impossible without decrypting the traffic. In order to be able to have multiple websites hosted on the same IP and port (443), the client is required to send the hostname before transport encryption is established. That's exactly what SNI does.
Usually SNI allows you to create different vhosts like this (pseudo code)
www.example.com:443
www.example.com settings
private.example.com:443
private.example.com settings
In HAProxy however, it looks more like this (pseudo code)
*:443
use_backend www if sni is www.example.com
use_backend private if sni is private.example.com
The problem here is, that a lot of settings are done in the frontend, not the backend and therefore some settings cannot be set vhost specific. I found a solution to this problem, which I documented on serverfault.com. If I find the time, I'll write a blog post that will explain everything in more detail.
Seriously, why is this never documented??? - following a howto about something that includes PostgreSQL on Ubuntu 14.04 is always a pain. Mainly because these two lines seem to be missing every single time!
$ sudo useradd -U -s /bin/bash postgres
$ sudo pg_createcluster 9.3 main --start
source: askubuntu.com
IPython Notebook - Looking for a new web based notebook? I did! And I found "IPython Notebook" which is, to keep it short, awesome.
To showcase a few of the many features I like...
Run Python code
Use Markdown
Preview
VIM modelines
VIM modelines look something like this
and can be used to set VIM settings for specific files. By appending the modeline, VIM will adjust the global settings accordingly, unless modelines is disabled.
Modelines can be temporarily enabled by running :verbose set modeline
or permanently by adding set modeling
to your ~/.vimrc
.
Note that modelines is off by default when editing as root..
VIM jar - VIM never ceases to amaze me, and the limit to things one can learn about it seems to be non-existent.
I looked for a tool to explore the contents of a jar file. As it turns out, it's just a zipped archive so unpack it and that's it - however, you could just open it with vim and have a look around without extracting the files first.
If you have unzip installed that is.
I usually use tar, so unzip is something I don't have installed by default but know I might just have enough reason to install it as well.
Kubuntu on L420 - Just a quick addition, I recently bought a Thinkpad L420 for 220€ on ebay. Unfortunately Kubuntu only booted with the acpi=off
and nolapic
flags. After a BIOS upgrade with this boot CD everything worked fine. Just in case anyone faces this issue as well.
Links - Interesting things I found on the webs


A polyfill to enable IndexedDB using WebSql.
IndexedDB is not supported on all browsers. This IndexedDB polyfill exposes the IndexedDB API in unsupported browsers using WebSQL. This shim is basically an IndexedDB-WebSql adapter.
Check out my blog for updates.
IndexedDB is not supported on all browsers. This IndexedDB polyfill exposes the IndexedDB API in unsupported browsers using WebSQL. This shim is basically an IndexedDB-WebSql adapter.
Check out my blog for updates.
Download
To keep the code manageable, the modules are in different files. The link above is simply a concatenation of all these files.
You can build a development
or production (minified)
version by running the default task in the gruntfile. The two files will be put in the
dist
folder.
You can also concantenate them again with JavaScript and download that copy using this link.
Test Cases
Libraries tested to work with the shim
The polyfill implements the IndexedDB API specification.
The following libraries have examples that work with the polyfill.
- JQuery-IndexedDB plugin - See example
- LINQ API for IndexedDB LINQ2IndexedDB
- PouchDB Examples - See examples
- DB.JS library - See Examples
Source Code
Fork the repository on github. The source code is licensed under Apache 2.0.
The implementation is not 100% to the spec and some work still needs to be done. There are a couple of open issues
to be fixed
Send out a pull request if you would like to help !!
Other IndexedDB links
Credits
A big thanks to the contributors
to this project.


Please cite this as:
Mills, M.C and Rahal, C., (2020).
'The GWAS Diversity Monitor Tracks diversity by disease in real time'.
Nature Genetics, 52, 242-243. doi: 10.1038/s41588-020-0580-y
Maintained by:
The Leverhulme Centre for Demographic Science
Accompanying code library:
Boef, N., Brunier, Q., Knowles, I., Malowany, A., May, J., Mills, M.C., Misseri, L., Nixon, G., Ntova, V., Rahal, C. and Sinclair, C., (2020). 'Source code for the GWAS Diversity Monitor', (Version v1.0.0). Zenodo. https://doi.org/10.5281/zenodo.3600472


Development Dashboard
Disconnected
Robot
Type
Material
Iron
Plastic
Planet
Earth
Mars
Intelligence
Happy


--- title: State Parties / Branches permalink: "/branches/" layout: default dark-theme: true branches: - state: act registration: Complete status: Looking for Executive Committee Members. name: The Flux Party — ACT - state: wa registration: Complete status: Preparing for upcoming WA State Election in March 2021. name: The Flux Party - WA - state: qld registration: Complete status: Preparing next Federal Election. name: The Flux Party Queensland - state: nsw registration: Complete status: Preparing next Federal Election. name: Flux Party (NSW) - state: tas registration: Application process ongoing - need more members in Tasmania. status: Need 100+ Statutory Declarations. Next Tasmanian state election in, or before, 2022 howToLink: http://www.electoral.tas.gov.au/pages/ElectoralInformation/Approvals/PDF/S44(1)%20-%20F44(1).pdf name: Name TBD - state: vic registration: Registering for 2022 election. Seeking more members and volunteers to build our network on the ground. status: Need 500 members, other requirements ambiguous howToLink: https://www.vec.vic.gov.au/CandidatesAndParties/RegisteringAPoliticalParty.html name: Name TBD - state: sa registration: Application process ongoing - need more members in South Australia status: Need 200 members howToLink: http://www.ecsa.sa.gov.au/parties-and-candidates/how-to-register-a-political-party name: Name TBD - state: nt registration: Application process ongoing - need more members in Northern Territory status: Need 200 members howToLink: http://www.ntec.nt.gov.au/CandidatesAndParties/RegistrationOfPoliticalParties/Pages/Party-Registration.aspx name: Name TBD --- {% include navbar.html %}


Not only is this site pretty broken, but it's out of date.
The manifesto was written in a time when it was hard to find high-quality components that weren't tied to heavy, "batteries-included" frameworks.
This has changed. Composer and packagist.org have done their job. Most heavy frameworks are made up of components now, and it's reasonable to pick and choose your tools at will.
PHP dev is in a much better place. Enjoy it. Use the tools you see fit.


OffscreenCanvas
is a relatively new browser feature currently only available in Chrome but apparently
coming to other browsers. OffscreenCanvas
allows a web worker to render
to a canvas. This is a way to offload heavy work, like rendering a complex 3D scene,
to a web worker so as not to slow down the responsiveness of the browser. It
also means data is loaded and parsed in the worker so possibly less jank while
the page loads.
Getting started using it is pretty straight forward. Let's port the 3 spinning cube example from the article on responsiveness.
Workers generally have their code separated into another script file whereas most of the examples on this site have had their scripts embedded into the HTML file of the page they are on.
In our case we'll make a file called offscreencanvas-cubes.js
and
copy all the JavaScript from the responsive example into it. We'll then
make the changes needed for it to run in a worker.
We still need some JavaScript in our HTML file. The first thing
we need to do there is look up the canvas and then transfer control of that
canvas to be offscreen by calling canvas.transferControlToOffscreen
.
function main() { const canvas = document.querySelector('#c'); const offscreen = canvas.transferControlToOffscreen(); ...
We can then start our worker with new Worker(pathToScript, {type: 'module'})
.
and pass the offscreen
object to it.
function main() { const canvas = document.querySelector('#c'); const offscreen = canvas.transferControlToOffscreen(); const worker = new Worker('offscreencanvas-cubes.js', {type: 'module'}); worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]); } main();
It's important to note that workers can't access the DOM
. They
can't look at HTML elements nor can they receive mouse events or
keyboard events. The only thing they can generally do is respond
to messages sent to them and send messages back to the page.
To send a message to a worker we call worker.postMessage
and
pass it 1 or 2 arguments. The first argument is a JavaScript object
that will be cloned
and sent to the worker. The second argument is an optional array
of objects that are part of the first object that we want transferred
to the worker. These objects will not be cloned. Instead they will be transferred
and will cease to exist in the main page. Cease to exist is the probably
the wrong description, rather they are neutered. Only certain types of
objects can be transferred instead of cloned. They include OffscreenCanvas
so once transferred the offscreen
object back in the main page is useless.
Workers receive messages from their onmessage
handler. The object
we passed to postMessage
arrives on event.data
passed to the onmessage
handler on the worker. The code above declares a type: 'main'
in the object it passes
to the worker. This object has no meaning to the browser. It's entirely for
our own usage. We'll make a handler that based on type
calls
a different function in the worker. Then we can add functions as
needed and easily call them from the main page.
const handlers = { main, }; self.onmessage = function(e) { const fn = handlers[e.data.type]; if (typeof fn !== 'function') { throw new Error('no handler for type: ' + e.data.type); } fn(e.data); };
You can see above we just look up the handler based on the type
pass it the data
that was sent from the main page.
So now we just need to start changing the main
we pasted into
offscreencanvas-cubes.js
from the responsive article.
Instead of looking up the canvas from the DOM we'll receive it from the event data.
-function main() { - const canvas = document.querySelector('#c'); +function main(data) { + const {canvas} = data; const renderer = new THREE.WebGLRenderer({antialias: true, canvas}); ...
Remembering that workers can't see the DOM at all the first problem
we run into is resizeRendererToDisplaySize
can't look at canvas.clientWidth
and canvas.clientHeight
as those are DOM values. Here's the original code
function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement; const width = canvas.clientWidth; const height = canvas.clientHeight; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; }
Instead we'll need to send sizes as they change to the worker. So, let's add some global state and keep the width and height there.
const state = { width: 300, // canvas default height: 150, // canvas default };
Then let's add a 'size'
handler to update those values.
+function size(data) { + state.width = data.width; + state.height = data.height; +} const handlers = { main, + size, };
Now we can change resizeRendererToDisplaySize
to use state.width
and state.height
function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement; - const width = canvas.clientWidth; - const height = canvas.clientHeight; + const width = state.width; + const height = state.height; const needResize = canvas.width !== width || canvas.height !== height; if (needResize) { renderer.setSize(width, height, false); } return needResize; }
and where we compute the aspect we need similar changes
function render(time) { time *= 0.001; if (resizeRendererToDisplaySize(renderer)) { - camera.aspect = canvas.clientWidth / canvas.clientHeight; + camera.aspect = state.width / state.height; camera.updateProjectionMatrix(); } ...
Back in the main page we'll send a size
event anytime the page changes size.
const worker = new Worker('offscreencanvas-picking.js', {type: 'module'}); worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]); +function sendSize() { + worker.postMessage({ + type: 'size', + width: canvas.clientWidth, + height: canvas.clientHeight, + }); +} + +window.addEventListener('resize', sendSize); +sendSize();
We also call it once to send the initial size.
And with just those few changes, assuming your browser fully supports OffscreenCanvas
it should work. Before we run it though let's check if the browser actually supports
OffscreenCanvas
and if not display an error. First let's add some HTML to display the error.
 <canvas id="c"></canvas> +
 +
no OffscreenCanvas support
 +

and some CSS for that
#noOffscreenCanvas { display: flex; width: 100%; height: 100%; align-items: center; justify-content: center; background: red; color: white; }
and then we can check for the existence of transferControlToOffscreen
to see
if the browser supports OffscreenCanvas
function main() { const canvas = document.querySelector('#c'); + if (!canvas.transferControlToOffscreen) { + canvas.style.display = 'none'; + document.querySelector('#noOffscreenCanvas').style.display = ''; + return; + } const offscreen = canvas.transferControlToOffscreen(); const worker = new Worker('offscreencanvas-picking.js', {type: 'module}); worker.postMessage({type: 'main', canvas: offscreen}, [offscreen]); ...
and with that, if your browser supports OffscreenCanvas
this example should work
So that's great but since not every browser supports OffscreenCanvas
at the moment
let's change the code to work with both OffscreenCanvas
and if not then fallback to using
the canvas in the main page like normal.
As an aside, if you need OffscreenCanvas to make your page responsive then it's not clear what the point of having a fallback is. Maybe based on if you end up running on the main page or in a worker you might adjust the amount of work done so that when running in a worker you can do more than when running in the main page. What you do is really up to you.
The first thing we should probably do is separate out the three.js code from the code that is specific to the worker. That way we can use the same code on both the main page and the worker. In other words we will now have 3 files
our html file.
threejs-offscreencanvas-w-fallback.html
a JavaScript that contains our three.js code.
shared-cubes.js
our worker support code
offscreencanvas-worker-cubes.js
shared-cubes.js
and offscreencanvas-worker-cubes.js
are basically
the split of our previous offscreencanvas-cubes.js
file. First we
copy all of offscreencanvas-cubes.js
to shared-cube.js
. Then
we rename main
to init
since we already have a main
in our
HTML file and we need to export init
and state
import * as THREE from 'three'; -const state = { +export const state = { width: 300, // canvas default height: 150, // canvas default }; -function main(data) { +export function init(data) { const {canvas} = data; const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
and cut out the just the non three.js relates parts
-function size(data) { - state.width = data.width; - state.height = data.height; -} - -const handlers = { - main, - size, -}; - -self.onmessage = function(e) { - const fn = handlers[e.data.type]; - if (typeof fn !== 'function') { - throw new Error('no handler for type: ' + e.data.type); - } - fn(e.data); -};
Then we copy those parts we just deleted to offscreencanvas-worker-cubes.js
and import shared-cubes.js
as well as call init
instead of main
.
import {init, state} from './shared-cubes.js'; function size(data) { state.width = data.width; state.height = data.height; } const handlers = { - main, + init, size, }; self.onmessage = function(e) { const fn = handlers[e.data.type]; if (typeof fn !== 'function') { throw new Error('no handler for type: ' + e.data.type); } fn(e.data); };
Similarly we need to include shared-cubes.js
in the main page


welcome To Salmon Cookies
Sales
Order
we are located:
Seatlle Open(6:00AM-8:00PM)
Tokyo Open(6:00AM-8:00PM)
Dubai Open(6:00AM-8:00PM)
Paris Open(6:00AM-8:00PM)
Lima Open(6:00AM-8:00PM)


rrricanes
is intended to give easy access to hurricane archives. It is a web-scraping tool that parses the National Hurricane Center’s (NHC) archives to get storm data. Data is available for storms dating back to 1998.
There are two basins which data is available: north Atlantic (“AL”) and northeastern Pacific (“EP”). The northeastern Pacific basin typically covers from the west coast of North America to -140° longitude (140°W).
By default, get_storms
will return all storms that have developed for the current year in both basins. If no storms have developed, an error will be generated. For this example, we’ll use 2012.
get_storm_data
can be used to retrieve one or multiple products for one or more cyclones. A list of dataframes is returned.
df.al_18_2012_fstadv <- df.al_2012 %>%
filter(Name == "Hurricane Sandy") %>%
.$Link %>%
get_storm_data(products = "fstadv")
We can get the forecast/advisory data and wind speed probabilities at once:
df.al_18_2012 <- df.al_2012 %>%
filter(Name == "Hurricane Sandy") %>%
.$Link %>%
get_storm_data(c("fstadv", "wndprb"))
df.al_18_2012
now contains two dataframes for Hurricane Sandy; fstadv
and wndprb
.
fstadv
)The core of a storm’s dataset is located in the Forecast/Advisory product, fstadv
. This product contains current location, forecast position, movement and structural details of the cyclone.
To access only this product, we can use get_fstadv
:
df.al_18_2012_fstadv <- df.al_2012 %>%
filter(Name == "Hurricane Sandy") %>%
.$Link %>%
get_fstadv()
As you may have noticed above, the dataframe is very wide at 149 variables. There are four groups of variables in this dataset: current details, current wind radii, forecast positions, and forecast wind radii.
Let’s look at an example of the current details.
## Classes 'tbl_df', 'tbl' and 'data.frame': 31 obs. of 18 variables:
## $ Status : chr "Tropical Depression" "Tropical Storm" "Tropical Storm" "Tropical Storm" ...
## $ Name : chr "Eighteen" "Sandy" "Sandy" "Sandy" ...
## $ Adv : num 1 2 3 4 5 6 7 8 9 10 ...
## $ Date : POSIXct, format: "2012-10-22 15:00:00" "2012-10-22 21:00:00" ...
## $ Key : chr "AL182012" "AL182012" "AL182012" "AL182012" ...
## $ Lat : num 13.5 12.5 12.7 13.3 13.8 14.3 15.2 16.3 17.1 18.3 ...
## $ Lon : num -78 -78.5 -78.6 -78.6 -77.8 -77.6 -77.2 -77 -76.7 -76.6 ...
## $ Wind : num 25 35 40 40 45 45 50 60 70 70 ...
## $ Gust : num 35 45 50 50 55 55 60 75 85 85 ...
## $ Pressure: num 1003 999 998 998 993 ...
## $ PosAcc : num 45 50 25 40 30 30 20 20 20 20 ...
## $ FwdDir : num 230 NA NA 360 20 20 15 10 15 10 ...
## $ FwdSpeed: num 4 NA NA 3 4 5 9 12 11 12 ...
## $ Eye : num NA NA NA NA NA NA 25 NA NA NA ...
## $ SeasNE : num NA 60 60 70 75 90 180 180 180 180 ...
## $ SeasSE : num NA 60 45 80 60 90 180 180 240 240 ...
## $ SeasSW : num NA 0 0 0 0 0 0 45 0 0 ...
## $ SeasNW : num NA 0 45 50 50 50 0 100 90 90 ...
The most important variable in this dataset is Key
. Key
is a unique identifier for each storm that develops in either basin. It is formatted such as “AABBCCCC” where “AA” is the basin abbreviation (AL or EP), “BB” is the year number of the storm left-padded, and “CC” is the year of the storm.
Adv
is the second-most important variable here. You’ll notice it is in character format. For regularly-scheduled advisories, advisory numbers are always numeric. However, when watches and warnings are in effect, intermediate advisories are issued which are given alpha suffixes; i.e., 1, 2, 3, 3A, 4, 4A, 4B, 5, etc.
Only the Public Advisory (public
) will be issued more frequently. All other regular products (discus
, fstadv
, prblty
, wndprb
) are generally issued every six hours.
Status
lists the current designation of the cyclone, i.e., Tropical Depression, Tropical Storm, etc. A Name
is given once a storm crosses the threshold of Tropical Storm; that is, winds greater than 33kts.
Lat
and Lon
are the current position of the storm within PosAcc
nautical miles. All distance measurements are in nautical miles.
Wind
and Gust
are current one-minute sustained wind speeds in knots (kts). You can use the function knots_to_mph
to convert this. All wind speed values are in knots.
Pressure
is the lowest atmospheric pressure of the cyclone either measured or estimated. It’s value is in millibars but you can use mb_to_in()
to convert to inches.
FwdDir
and FwdSpeed
show the compass direction of the forward movement of the cyclone. NA values indicate the storm is stationary or drifting. FwdSpeed
is measured in knots.
In some cases, where hurricanes have an identifiable Eye
, it’s diameter in nautical miles will also be listed.
Lastly, the Seas
variables will exist for a storm of at least tropical storm-strength. This is the distance from the center of circulation that 12ft seas can be found in each quadrant. The measurement is in nautical miles.
Helper function tidy_fstadv
will subset this data to a narrow dataframe.
## Warning: `tidy_fstadv is deprecated and will be removed in v0.2.2
## # A tibble: 31 x 18
## Key Adv Date Status Name Lat Lon Wind Gust
## <chr> <dbl> <dttm> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 AL18… 1 2012-10-22 15:00:00 Tropi… Eigh… 13.5 -78 25 35
## 2 AL18… 2 2012-10-22 21:00:00 Tropi… Sandy 12.5 -78.5 35 45
## 3 AL18… 3 2012-10-23 03:00:00 Tropi… Sandy 12.7 -78.6 40 50
## 4 AL18… 4 2012-10-23 09:00:00 Tropi… Sandy 13.3 -78.6 40 50
## 5 AL18… 5 2012-10-23 15:00:00 Tropi… Sandy 13.8 -77.8 45 55
## 6 AL18… 6 2012-10-23 21:00:00 Tropi… Sandy 14.3 -77.6 45 55
## 7 AL18… 7 2012-10-24 03:00:00 Tropi… Sandy 15.2 -77.2 50 60
## 8 AL18… 8 2012-10-24 09:00:00 Tropi… Sandy 16.3 -77 60 75
## 9 AL18… 9 2012-10-24 15:00:00 Hurri… Sandy 17.1 -76.7 70 85
## 10 AL18… 10 2012-10-24 21:00:00 Hurri… Sandy 18.3 -76.6 70 85
## # … with 21 more rows, and 9 more variables: Pressure <dbl>, PosAcc <dbl>,
## # FwdDir <dbl>, FwdSpeed <dbl>, Eye <dbl>, SeasNE <dbl>, SeasSE <dbl>,
## # SeasSW <dbl>, SeasNW <dbl>
Any cyclone of at least tropical storm-strength will have associated wind radius values. This is the distance from the center of circulation that a specified wind speed (34kts, 50kts, 64kts) can be found in each quadrant. Measurement is in nautical miles.
## Classes 'tbl_df', 'tbl' and 'data.frame': 31 obs. of 12 variables:
## $ NE64: num NA NA NA NA NA NA NA NA 20 25 ...
## $ SE64: num NA NA NA NA NA NA NA NA 20 20 ...
## $ SW64: num NA NA NA NA NA NA NA NA 0 0 ...
## $ NW64: num NA NA NA NA NA NA NA NA 0 0 ...
## $ NE50: num NA NA NA NA NA NA 0 50 50 50 ...
## $ SE50: num NA NA NA NA NA NA 80 70 60 60 ...
## $ SW50: num NA NA NA NA NA NA 0 0 30 40 ...
## $ NW50: num NA NA NA NA NA NA 0 0 30 40 ...
## $ NE34: num NA 50 50 70 70 80 90 100 110 110 ...
## $ SE34: num NA 60 60 80 80 90 120 120 120 120 ...
## $ SW34: num NA 0 0 0 0 0 0 45 60 70 ...
## $ NW34: num NA 0 0 0 0 0 30 45 60 60 ...
A helper function, tidy_wr
will reorganize this data into a narrow format and tidied up. Complete wind radius values that are NA are removed for efficiency.
## # A tibble: 77 x 8
## Key Adv Date WindField NE SE SW NW
## <chr> <dbl> <dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AL182012 2 2012-10-22 21:00:00 34 50 60 0 0
## 2 AL182012 3 2012-10-23 03:00:00 34 50 60 0 0
## 3 AL182012 4 2012-10-23 09:00:00 34 70 80 0 0
## 4 AL182012 5 2012-10-23 15:00:00 34 70 80 0 0
## 5 AL182012 6 2012-10-23 21:00:00 34 80 90 0 0
## 6 AL182012 7 2012-10-24 03:00:00 34 90 120 0 30
## 7 AL182012 7 2012-10-24 03:00:00 50 0 80 0 0
## 8 AL182012 8 2012-10-24 09:00:00 34 100 120 45 45
## 9 AL182012 8 2012-10-24 09:00:00 50 50 70 0 0
## 10 AL182012 9 2012-10-24 15:00:00 34 110 120 60 60
## # … with 67 more rows
Most Forecast/Advisory products will have forecast data associated with it unless the storm has dissipated or is no longer tropical. There may be up to seven forecast positions. These positions are issued by 12-hour intervals through 48 hours where they are then at 24-hour intervals; 12, 24, 36, 48, 72, 96 and 120 hours.
Notice each variable begins with the prefix “Hrn” where n is the forecast period as noted above. Only Date, Lat, Lon, Wind, Gust and wind radius (will discuss shortly) are given for forecast periods.
Use tidy_fcst
to tidy forecast data.
## # A tibble: 216 x 8
## Key Adv Date FcstDate Lat Lon Wind
## <chr> <dbl> <dttm> <dttm> <dbl> <dbl> <dbl>
## 1 AL18… 1 2012-10-22 15:00:00 2012-10-23 00:00:00 13.7 -78.3 35
## 2 AL18… 1 2012-10-22 15:00:00 2012-10-23 12:00:00 14.3 -78.1 45
## 3 AL18… 1 2012-10-22 15:00:00 2012-10-24 00:00:00 15.7 -77.6 55
## 4 AL18… 1 2012-10-22 15:00:00 2012-10-24 12:00:00 17.4 -77 60
## 5 AL18… 1 2012-10-22 15:00:00 2012-10-25 12:00:00 20.5 -76 55
## 6 AL18… 1 2012-10-22 15:00:00 2012-10-26 12:00:00 24.5 -74.5 55
## 7 AL18… 1 2012-10-22 15:00:00 2012-10-27 12:00:00 27 -73 50
## 8 AL18… 2 2012-10-22 21:00:00 2012-10-23 06:00:00 13.6 -78.5 35
## 9 AL18… 2 2012-10-22 21:00:00 2012-10-23 18:00:00 14.9 -78.3 45
## 10 AL18… 2 2012-10-22 21:00:00 2012-10-24 06:00:00 16.4 -77.8 55
## # … with 206 more rows, and 1 more variable: Gust <dbl>
A note about forecast times.
## # A tibble: 1 x 2
## Date Hr12FcstDate
## <dttm> <dttm>
## 1 2012-10-22 15:00:00 2012-10-23 00:00:00
Notice the Date
of this advisory is Oct 22 at 15:00 UTC. The Hr12FcstDate
is Oct 23, 00:00 UTC. This difference, obviously, is not 12 hours. What gives? Forecast/Advisory products are issued with two “current” positions: one that is current (and provided in the dataset) and a position from three hours prior. So, in this specific advisory the text would contain the position of the storm for Oct 22, 12:00 UTC. It is from this position the forecast points are based. I do not know why.
Therefore, while officially the forecast periods are 12, 24, 36, … hours, in reality they are 9, 21, 33, … hours from the issuance time of the product.
Some forecast positions may also contain wind radius information (only up to 72 hours).
Again, these variables are prepended with the prefix prefix “Hrn” where n notes the forecast period.
tidy_fcst_wr
will tidy this subset of data.
## # A tibble: 337 x 9
## Key Adv Date FcstDate WindField NE
## <chr> <dbl> <dttm> <dttm> <dbl> <dbl>
## 1 AL18… 1 2012-10-22 15:00:00 2012-10-23 00:00:00 34 40
## 2 AL18… 1 2012-10-22 15:00:00 2012-10-23 12:00:00 34 50
## 3 AL18… 1 2012-10-22 15:00:00 2012-10-24 00:00:00 34 80
## 4 AL18… 1 2012-10-22 15:00:00 2012-10-24 00:00:00 50 30
## 5 AL18… 1 2012-10-22 15:00:00 2012-10-24 12:00:00 34 90
## 6 AL18… 1 2012-10-22 15:00:00 2012-10-24 12:00:00 50 40
## 7 AL18… 1 2012-10-22 15:00:00 2012-10-25 12:00:00 34 200
## 8 AL18… 1 2012-10-22 15:00:00 2012-10-25 12:00:00 50 50
## 9 AL18… 2 2012-10-22 21:00:00 2012-10-23 06:00:00 34 50
## 10 AL18… 2 2012-10-22 21:00:00 2012-10-23 18:00:00 34 50
## # … with 327 more rows, and 3 more variables: SE <dbl>, SW <dbl>, NW <dbl>
Please see the National Hurricane Center’s website for more information on understanding the Forecast/Advisory product.
prblty
)Strike probabilities were discontinued after the 2005 hurricane season (replaced by Wind Speed Probabilities; wndprb
). For this example, we’ll look at Hurricane Katrina. For this we use the function get_prblty
.
df.al_12_2005_prblty <- get_storms(year = 2005, basin = "AL") %>%
filter(Name == "Hurricane Katrina") %>%
.$Link %>%
get_prblty()
## Classes 'tbl_df', 'tbl' and 'data.frame': 937 obs. of 10 variables:
## $ Status : chr "Tropical Depression" "Tropical Depression" "Tropical Depression" "Tropical Depression" ...
## $ Name : chr "Twelve" "Twelve" "Twelve" "Twelve" ...
## $ Adv : chr "1" "1" "1" "1" ...
## $ Date : POSIXct, format: "2005-08-23 21:00:00" "2005-08-23 21:00:00" ...
## $ Location: chr "25.0N 77.7W" "JACKSONVILLE FL" "25.7N 78.5W" "SAVANNAH GA" ...
## $ A : num 50 0 36 0 19 0 0 0 0 0 ...
## $ B : num 0 0 0 0 6 0 1 0 0 5 ...
## $ C : num 0 2 0 0 1 0 0 0 0 3 ...
## $ D : num 0 9 1 6 1 3 3 2 2 5 ...
## $ E : num 50 11 37 6 27 3 4 2 2 13 ...
This dataframe contains the possibility of a cyclone passing within 65 nautical miles of Location
. The variables A
, B
, C
, D
, and E
are as they appear in the products and were left as-is to avoid confusion. They’re definition is as follows:
A
- current through 12 hours.B
- within the next 12-24 hoursC
- within the next 24-36 hoursD
- within the next 36-48 hoursE
- Total probability from current through 48 hours.Many values in the text product may be “X” for less than 1% chance of a strike. These values are converted to 0 as the fields are numeric.
The strike probability products did not contain Key
which is the unique identifier for every cyclone. So the best way to do any joins will be by Name
, Adv
and Date
.
Strike Probabilities may not exist for most Pacific cyclones.
wndprb
)df.al_18_2012_wndprb <- df.al_2012 %>%
filter(Name == "Hurricane Sandy") %>%
.$Link %>%
get_wndprb()
## Classes 'tbl_df', 'tbl' and 'data.frame': 2227 obs. of 18 variables:
## $ Key : chr "AL182012" "AL182012" "AL182012" "AL182012" ...
## $ Adv : num 1 1 1 1 1 1 1 1 1 1 ...
## $ Date : POSIXct, format: "2012-10-22 15:00:00" "2012-10-22 15:00:00" ...
## $ Location : chr "FT PIERCE FL" "W PALM BEACH" "MIAMI FL" "MARATHON FL" ...
## $ Wind : num 34 34 34 34 34 34 34 50 64 34 ...
## $ Wind12 : num 0 0 0 0 0 0 0 0 0 0 ...
## $ Wind24 : num 0 0 0 0 1 0 0 0 0 0 ...
## $ Wind24Cum : num 0 0 0 0 1 0 0 0 0 0 ...
## $ Wind36 : num 0 0 0 0 1 0 0 0 0 0 ...
## $ Wind36Cum : num 0 0 0 0 2 0 0 0 0 0 ...
## $ Wind48 : num 0 0 0 0 1 0 0 0 0 0 ...
## $ Wind48Cum : num 0 0 0 0 3 0 0 0 0 0 ...
## $ Wind72 : num 0 0 0 0 0 0 3 0 0 5 ...
## $ Wind72Cum : num 0 0 0 0 3 0 3 0 0 5 ...
## $ Wind96 : num 1 2 3 2 0 5 10 3 1 12 ...
## $ Wind96Cum : num 1 2 3 2 3 5 13 3 1 17 ...
## $ Wind120 : num 2 2 1 1 0 3 5 2 0 3 ...
## $ Wind120Cum: num 3 4 4 3 3 8 18 5 1 20 ...
Wind Speed Probabilities are a bit more advanced than their predecessor. The Wind
variable is for 34kt, 50kt and 64kt winds expected within a specific time period.
Each consecutive variable is within a specific time-frame (12, 24, 36, 48, 72, 96 and 120 hours) for both that time frame and cumulative.
For example, Wind24
is the chance of Wind
between 12-24 hours. Wind24Cum
is the cumulative probability from Date
through 24 hours.
As with strike probabilities, an “X” in the original text product meant less than 0.5% chance for the specified wind in the specified time period. “X” has been replaced by 0 in this package.
Wind Speed Probabilities may not exist for most Pacific cyclones.
See Tropical Cyclone Wind Speed Probabilities Products for more information.
Other products are available:
get_public
for Public Advisory statements. Think general information for the public audience. May not exist for some Pacific cyclones. Additionally, when watches and warnings are issued, these are issued every 3 hours (and, in some cases, every two).
get_discus
for Storm Discussions. These are more technical statements on the structure of a storm, forecast model tendencies and satellite presentation.
get_update
These are brief update statements when something considerable has changed in the cyclone or if the cyclone is making landfall.
get_posest
. Position estimates are generally issued when a storm is making landfall and may be issued hourly.
Hurricane Ike, 2008, has both updates and position estimates.
At this time none of these products are parsed. Only the content of the product is returned.


Reports JUnit4 tests which can be automatically converted to JUnit5. Though default runners are automatically convertable, custom runners, method- and field- rules are not and require manual changes.
New in 2017.1


the node automation was dev cause I had a job and no way to have a ssh during the day :p
I also wanted to share and have a way to monitor any node without any harm
just with a json sending
nothing else
1
cause at start we had to rely on different branchez and a way of tracking this without risk
is to just produce a standarfized json at regular interval
deposit this to a webserv and you got notarystats.com
I wznted it to be spread to all NN, but noone seemed to consider those infos crucial, or at least not enough(edited)
so deprecated lazynode and moved on
But the goal was also to refine the notary network
am sure with a basic script without any dependency we can produce a wellformed json
any op just need to push it to a designatef webserver and we have a real live monitoring
but in case of emergency... knowing who is on what branch is imo very important and we can make direct calls to operators and be more precise(edited)
instead of saying : please update
don t get cocky we ll get attacked and noone is awaken 24/7
so with a yes I know it feels baaaad, but centralized json... we basically can have live alerts on anything (I realize we re on general, sry)(edited)
2
we got the chance to operate in different timezones, this could help ^.^
1
1
1
blackjok3r16-Apr-19 01:20 AM
I fear unless the amount of SH nodes is increased, it will always relatively suck compared to AR/EU/NA
The thing we should really focus on is nerfing the ping advantage of iguana without comprimising reliability of ntoarizations.(edited)
PTYX16-Apr-19 01:23 AM
maybe placing them in places other than australia will help. we're looking for options in south america.
blackjok3r16-Apr-19 01:23 AM
That will; amke node in Aus even worse
you can make SH better if you put all nodes in Brazil
1
but that doesnt really achaive anything... the idea is to have nodes in as many countries as possible
With the current system there is no way that is going to happen, because greed...
Deleted User16-Apr-19 01:34 AM
lol
#notarynode may be more adapted(edited)
but we may have a workaround for this
people don t like this idea
but well executed it can be handy
NutellaLicka16-Apr-19 01:36 AM
Its a good discussion for everyone to see imo
Deleted User16-Apr-19 01:36 AM
just use alternate networks
NutellaLicka16-Apr-19 01:36 AM
And no tor dwy
:P
Deleted User16-Apr-19 01:36 AM
performance is an issue with tor
and maybe also regulations in spexif countries
blackjok3r16-Apr-19 01:39 AM
We tried tor it falt out does not work I can tell you right now
Deleted User16-Apr-19 01:40 AM
I ll try it if I got the chance to, this year
blackjok3r16-Apr-19 01:40 AM
Also creating our own tor ... where you use notary nodes themselgf to ping packets a random number of times before arrivinga t destination, will not work as statistically over time, nodes close to each other will still group together.
The answer is to just slow down revcmask a bit but not too mcuh.. I still dont know how to do this though.

Deleted User16-Apr-19 01:43 AM
lol
NutellaLicka16-Apr-19 01:45 AM
There is a fine line between a "crappy" node, and a node that doesnt work though
blackjok3r16-Apr-19 01:54 AM
YEs that is the problem with slowing it down. It would be a hardforking change, so a testnet would be needed (liekly with 64 ndoes aswell) so not an easy task to tune it right.
 This version is an early release with @KomodoPlatform and #Unity support, and not intended to be production ready at all. Still, great news though! #K64
Aron“XuanLeeeeee“Goldberg16-Apr-19 07:51 AM
Is there a Komodo channel on WeChat? I've been reading more and more recently that many people from China are asking for a Chinese komodo channel, and that discord is blocked in china. China is a big market as we all know, maybe you should be active there....?!
2019 will bring #LightningNetwork based games!
We are not so far away from the fully decentralized #poker #game over lightning network, called @pangeachips and backed by @KomodoPlatform.
Check out here: https://t.co/ZJKuFYnC7A
@sg777z @iMyloMylo @PassCombo @Mr...
MdAmazing16-Apr-19 12:46 PM
Online poker definitely needs revolutionised. Is there going rake?
jl777c16-Apr-19 12:47 PM
each person that runs dealer node can set the rake
part of it goes to PANGEA
MdAmazing16-Apr-19 12:48 PM
Nice setup competitive I'm sure with exisiting poker companies aka rake is better pokerstars lol
TonyL16-Apr-19 12:49 PM
Pokerstars casino now more than pokerroom lol
Partypoker doing good moves 2018-19 - they should take the lead imo
Or CHIPS (edited)
freakbros16-Apr-19 12:50 PM
MdAmazing16-Apr-19 12:56 PM
After pokerstars got rid of supernova scheme I stopped playing. So I'm excited for something new.
There's been a lot of talk about more rake being better, protecting the recreational players, and screwing over the Supernova players at PokerStars. It's fin...
MdAmazing16-Apr-19 01:19 PM
Yeah quality entertainment
p.16-Apr-19 01:22 PM
negreanu is scum
1
I was supernova every year hate stars
they 2 outered my friend yesterday final 2 tables of the 10m gtd
Team Chainstrike will run for two more nodes in NA & AR for #Komodo #VOTE2019 notary election! Feel free to check our details at https://t.co/ncdQhI2R4V and send your votes to one of our addresses. #crypto #blockchain #komodoplatform #iguana #notary #nodes #vote @dukeleto
jorian16-Apr-19 02:14 PM
#notary-node-alarms check for yourself whether is a good idea
ComputerGenie 👴👴👴16-Apr-19 02:15 PM
........................................
$tefano.16-Apr-19 02:15 PM
hi guys a quick question about asset chain
create a 100% pos coin with half premine and max coin at double of premine
./komodod -ac_name=HELLOWORLD -ac_supply=1000000 -ac_reward=5000000000
-ac_end=20000 -ac_staked=100 &
it's correct?(edited)
jorian16-Apr-19 02:16 PM
@blackjok3r or @Alright will advise you not to make a 100% pos chain
Alright16-Apr-19 02:16 PM
not uhhh
jorian16-Apr-19 02:16 PM
but if you want it, then it seems correct
$tefano.16-Apr-19 02:16 PM
indeed it's my question ..
Alright16-Apr-19 02:16 PM
That is fine, just understand how to properly distribute UTXOs
$tefano.16-Apr-19 02:16 PM
best to have 99 pos and 1 pow?
jorian16-Apr-19 02:16 PM
apart from the space between supply and reward
ComputerGenie 👴👴👴16-Apr-19 02:17 PM
100% PoS > 100% PoW
Alright16-Apr-19 02:17 PM
I have a script that will start them for you and manage UTXOs automatically if you like


Thoughts of Richard Browning.
Richard was the fourth child born to Charles Henry and Viola Rebecca McFate Browning. His siblings were Geneva who was married to Clyde Thomas, Cleo who was married to Norma Bean and Florence. Rich was only 8 years old when his mother quite unexpected passed away. Charles remarried after his wife’s passing as Floss and Rich were still at home and he need a mother for them. Dad married Emma Margaret Hill, a single divorced mother with two children Margaret and Floyd Robert (Bob). To that marriage was born 3 boys, LeRoy, Kenneth H and Dan Irven.
During World War II Rich joined the U.S. Army and went to Basic Training. Rich being 16 years older than I am, my 1st remember of him was that he was in the Army. I remember when he returned and then he was soon off to work. I know that both Rich and Cleo were color blind, but very little else.
I don’t remember anything about Rich and Lois’s wedding but I remember when they came to our home shortly after they were married. I thought that Lois was the most beautiful lady that I had ever seen. She really made an impression on me and I hoped that I might someday have a wife like that. Another thing I have always remembered about that visit. Mom had painted the back porch a light green. Some of us, including Rich, were sitting out on the pouch. As Lois came out, Rich looked at her and made the comment that her dress was the same color as the porch. To this, we all laughed because Lois’s dress was a pretty red.
I remember other hummer’s incidence as to his color blindness. One day Irven and I were riding with Rich and Lois and the subject came up. I asked Rich the color of their car, it was a light green, and Rich said he wasn’t sure. This brought up a few more questions concerning colors until Irven asked him what color is that green light was on the dash. When Rich answered that is was green, Irven said, I didn’t think you could tell colors. Another time that I was with Rich and Lois, in the car, it was fairly early in the morning and there wasn’t any other traffic as of yet, and Rich was driving, Rich drove through a red light. Neither Lois nor I said anything. At the next intersection the light was again red and Rich went right through it. At the third light that had turned green, Rich began to apply the brake and slow down. Lois then spoke up, saying “I know the problem, the lights are upside down. Rich was going on the position of the lit light and not the color.
Rich later told me of some of his military experances. He said that during the Basic Training program he mainly remembered the marching. He said seemed to be endless. He also told of crawling in full battle gear under bobbed wire with machine gun firing live ammunition over their head. He said that during that exercise, a solder crawled into a rattle snake.  He also told of being marched out into the desert until they were tired and then told that they had (only a short time) to dig a fox hole deep enough that a tank could run over them and they would not get hurt. He said that most of them thought this was a joke and non-saliently started digging. He said that speed changed dramatically when they saw the long row of tanks come over the horizon towards them. He said that as the tank went over them the tracks would sink several inches into the earth under the weight of the tank.
As basic training concluded he said that his company was marched to a nice grassy area. They were seated under the shade of trees and given lemon aid. The Company Commander then spoke to them about the need for Paratroopers. Rich said that they should have been aware that something was up, with the grass; the shade; the lemon aid and the officer not use any foul language. The Company Commander encouraged them to volunteer. He promised those that volunteered that they would never have to march again. At the conclusion they were told that anyone under 21 had to have parental consent. There were 6 young men from the valley that all joined at the same time. All six wrote home but Dad was the only one that gave his permission. Interestingly, Rich was the only one of those 6 that was not killed in action. Rich also told me that as far as the “Never having to March again”, he said that was correct for as soon as they were accepted into Paratrooper Training, they ran to the barrack, rolled up their belongings into their mattress, placed the mattress on their heads and ran to their new barracks. Rich said all the rest of their training was on a full run.
Rich never had to jump behind enemy lines. Several times they were set to go behind the lines but something always came up, usually weather conditions and the jump was canceled. The last jump was a sure thing and their plane was making its final check before leaving the runway when D day was announced. I asked Rich if it scarred him to jump and he said he never got over being afraid but if you hesitated going out the door there was a big boot that shoved you out.
Worked with Rich, during summer school vacation in 1953, 1954 & 1955, helping him with the haying. There are many stories that can be told about those summers.
Rich and I both must have learned about finances, from our father. Dad never was very good at his financial dealings with others. Dad believed that your word and a hand shake was all the contract that you needed. He had many that took advantage of him, but Dad never reminded anyone of their promise to pay. I think Rich had several that took advantage of him. In all the time I spent with Rich I don’t remember of him getting upset at anyone. I don’t recall of him ever criticizing others and I never heard him swore.
As Rich and Lois’s family grew up, I noticed that they bought several Snowmobiles. On one occasion while we were visiting with them I asked Rich how he could afford the snowmobiles. He said that he really couldn’t but he had to because he was losing contact with his boys. Rich explained that his sons were getting some height, where he took after our father who was just a little over 5 feet tall.  Rich said that he couldn’t compete with them on those sorts, so he bought a snowmobile and the boys came back. Then he had to buy more as one person was not safe to ride very far by their self, plus they needed enough so that they could all go together. I can tell you that Rich could compete with almost anyone on snowmobils. Mae and I had several opportunities to spend time with Rich and Lois in the Island Park area. Rich took us up Two Top, which in itself is quite a ride. You are on top of the Continental Divide and can see clear for miles, including the Teton Peaks area. The blowing wind made great snow monsters of the trees and would blow a solid pack out over the East side that dropped off more than a straight drop. As we were looking over the valley below, Rich asked me if I wanted to go off the edge with him. I looked at him questioningly and asked him if he was kidding. He responded “No! You just count to three, hit the throttle and lean back. You will free fall 75 to 100 feet when the back end of the snowmobile will hit snow and then the front end will tip down. He said that they had done it before with no problems. He also said that you need two to go together in case one has problems, then the other can help out.” I told him that if he went first, he would be all by himself because I wasn’t going over that edge.
Condo
Lions head, Iraland park


--- layout: archive title: Zulip Chat Archive permalink: /stream/113488-general/topic/User.20definable.20options.html ---
Is there a way that I can set user definable options that can be parsed by tactics? I have some proofs that take a while to run, and I'd like to be able to have an option at the file or lean package level that let me configure whether they ran or not. e.g., during interactive development I disable proofs I'm not actually working on, but in a regression test they are enabled.
I noticed within a single run of the tactic monad, I can set custom option names (e.g., set_options (opt.set_bool "enable_unsafe_tac" tt)
), but the value doesn't appear to show up in tactics farther down the file. The set_option command also doesn't allow custom options.
set_option
accepts only built-in options, but using the set_options
primitive should work. Did you execute that code in a run_command
?
Sorry for the delay; I didn't see this until today. Here's a sample script:
open tactic meta def get_my_opt : tactic unit := do o ← get_options, trace (repr (o.get_bool "foo" ff)) meta def set_my_opt : tactic unit := do o ← get_options, set_options (o.set_bool "foo" tt), get_my_opt run_cmd get_my_opt run_cmd set_my_opt run_cmd get_my_opt
The output I get is:
ff tt ff
So set_options
works in the current command, but the option is forgotten in subsequent commands.
Ah, that's too bad. You may want to fake the option with a custom attribute (which can be set globally or locally, but unset only locally). I'm not aware of a better solution.
Thanks, that seems to work well.
Is this improving in lean 4? More generally, it would be nice if there was a way to persist arbitrary data across different commands. Does everything have to go via adding defs to the environment?
I could see use cases for persisting data, but I also think it's important that tactics could be run concurrently, and the results cached. Given that goal, set_options
behavior doesn't seem to surprising.
In Haskell, you can define package level options and use them to define constants that can be checked at compile time (via CPP). That's what I was hoping for here, so I could pass a flag to build or configure that controlled whether an axiom was allowed to be used. The attribute trick doesn't seem too bad though.
Last updated: Apr 24 2020 at 19:02 UTC


{% load i18n %} {% url 'dashboard' as dashboard_url %} {% blocktrans with username=proposal.speaker.name site_name=current_site.name title=proposal.title %}
{{ username }} attached you as an additional speaker to a talk proposal for {{ site_name }} entitled "{{ title }}".
For more details, visit the {{ site_name }} speaker dashboard: https://{{ current_site }}{{ dashboard_url ]}
{% endblocktrans %}


C. Subramaniya Bharathiyar Songs - Part IV
(pAnjcAli capatam -part I)
in Tamil Script, unicode/utf-8 format
சி.சுப்ரமணிய பாரதியார் பாடல்கள் - பாகம் 4
பாஞ்சாலி சபதம் (முதற் பாகம் )
Etext Preparation: Ms.Veena Jayaraman, Texas, USA (input), Dr. N. Kannan, Kiel, Germany (proof-reading)
Web version: K. Kalyanasundaram, Lausanne, Switzerland
This webpage presents the Etext in Tamil script but in Unicode encoding.
To view the Tamil text correctly you need to set up the following:
i). You need to have Unicode fonts containing Tamil Block (Latha,
Arial Unicode MS, TSCu_Inaimathi, Code2000, UniMylai,...) installed on your computer
and the OS capable of rendering Tamil Scripts (Windows 2000 or Windows XP).
ii)Use a browser that is capable of handling UTF-8 based pages
(Netscape >4.6, Internet Explorer 5) with the Unicode Tamil font
chosen as the default font for the UTF-8 char-set/encoding view. .
In case of difficulties send an email request to
kalyan@geocities.com


Pornhub Hilariously Trolls 20 Million People Who Just Failed No Nut November
by Emma RosemurgeyAh, November. The month we get to celebrate bonfire night; the month where radios start playing all the classic Christmas tunes; and the month where men challenge themselves not to ejaculate for the entire 30 days.
No, I’d never heard of the latter either, but after doing some light googling I can confirm ‘No Nut November’ is a real thing, and the rules are simple.
Men essentially have to go 30 days without ‘busting a nut’ – or ejaculating, for us folk who don’t speak the laddy lingo. That means no masturbating, no having sex and no doing anything that could possibly lead to breaking the challenge.
The Urban Dictionary defines No Nut November as:
An ancient ritual that must be performed by one man every thousand years. This man must have a will stronger than any other, and must defy his destiny of being a common man to save all of humanity. This man must control his primal urges, to go without nutting for the entire month of November. This man is you, Dankuya. Defy your destiny and save humanity, the fate of the world rests in your hands.
As I write this, it’s two days into No Nut November, but it seems men all over the globe have failed stick to their temporary celibacy. In fact, Pornhub has confirmed it.
The adult video hosting site (let’s be real, you already knew what it was) took to Twitter yesterday to hilariously troll everyone for not sticking to their jizz-free commitment on the very first day of the month.
’20 million people already failed No Nut November,’ Pornhub wrote on Twitter, adding, ‘Weak.’
A second tweet continued with an update stating 100 million ‘have now fallen’. It then added, ‘To the soldiers still going strong, we salute you. Only 29 days to go.’
Now, I can only assume Pornhub is insinuating everyone who has watched one of their videos has ‘busted a nut’, which is a pretty bold claim.
What if they just like the storylines? Of course, I’m kidding.
According to Urban Dictionary, anyone who successfully makes it through the 30 days of celibacy automatically qualifies through to Destroy Dick December, which quite frankly, I wouldn’t recommend.
To anyone setting out on this challenge, I wish you good luck with the rest of your endeavour. You’ve got this.
Emma Rosemurgey is an NCTJ trained Journalist who started her career by producing The Royal Rosemurgey newspaper in 2004, which kept her family up to date with the goings on of her sleepy north east village. She graduated from the University of Central Lancashire in Preston and started her career in regional newspapers before joining Tyla (formerly Pretty 52) in 2017, and progressing onto UNILAD in 2019.


{% extends "template.html" %} {% block head %} {% endblock %} {% block content %} {#
select a paper to submit(Only pdf files are allowed)
Notes:pdf file < 20MB is allowed


All Classes
AddMember
ClassSQL
EditMember
Inter
Local
Mainmenu
MemberModel
ReadWrite
SearchMember
SoccerMemberSystem
SQLConnection
User
Validator


WITNESS LIST S/C on Capital Funding for Higher Education Committee May 12, 2006 - 4:30P HB 153 Registering, but not testifying: On: Cigarroa, M.D., Francisco G. President (UT Health Science Center San Antonio), San Antonio, TX Garcia, Jose VP for Finance and Administration (Texas A&M International University), Laredo, TX Keck, Ray M. University President (Texas A&M International University), Laredo, TX Killebrew, Flavius C. President (Texas A&M University - Corpus Christi), Corpus Christi, TX


RCS 2 / Advanced Messaging - implementation research
Recently, I was doing some studies on implementation of Advanced Messaging / RCS 2 as a channel for chat bots.
The client implementation seems to be Android Messages.
This platform needs to expose it’s APIs so that our bots can access it. The core people working on RCS / Advanced Messaging are Jibe. They seems to be in process of providing Advanced Messaging / RCS 2 APIs but technically there’s nothing ready.
Was having a look at the Solaiemes RCS API. Solaiemes is the subsidiary of Mavenir/Xura. At this point, it’s API end points are not working:
- http://api.2445580839652.proxy.3scale.net:80/rcsapi/session
- https://tadhack.solaiemes-rcs-api.3scale.net/rcsapi
- https://tadhack.3scale.net/rcsapi
- http://tadhack.solaiemes.com/rcsapi
The following provider seems to be in a position to provide RCS 2 / Advanced Mesaging APIs:
The following vendors are yet to confirm whether they support Advanced Messaging / RCS 2:
- Twilio
- Solaiemes - end points not woring, probably closed
- Muut
- Symsoft
- MessageBird
- Summit Tech
- RCS
- Nablecomm
- RCS-RDS
- NewPace
- Infinite Convergence
- ZTE
- Utimaco
- Media 5 Corp
- Acision
- Newnet Mobility
- Wit Software
- TelesTax
- Tropo
- Tatango
- Interop
- 3C
- Experian
- M Gage
- Mobivity
- Movile messaging
- Nexmo
- Open market
- Waterfall
- Zip Whip
As of april’2017, the following vendors do not support Advanced Messaging
Although, GSMA is not supposed to, and has not responded to our technical questions. GSMA has specified RCS API requirements so far.
Btw, what is RCS?
Features of Advanced Messaging
- Ubiquity
- Simplicity
- Everyone is invited
- All the features
- Enhanced messaging experience
WHAT IS ‘MESSAGING AS A PLATFORM (MAAP)?
To most users messaging is just an ‘app’ – a program on their phones they use to keep in touch. Advanced Messaging will change that though – messaging is now becoming a ‘platform’ on which applications will be built to deliver whole new levels of interaction and experience.
It is where SMS is headed. End-users simply want all the services they need as quickly and conveniently as possible, and MaaP lets operators deliver that. If you want to book a taxi, a flight or look up train times for example, you will not need to download a specific new app – just hit your messenger.
MaaP removes that barrier of another app to download and connects suppliers directly to consumers. Messaging as a Platform will give operators all new possibilities for developing and implementing innovative services, and most importantly, for generating new revenues.
The potential for Messaging as a Platform
One of the more striking developments of messaging in recent times has been the evolution of messaging apps and clients into the ‘new home page’. End-users pick up their mobile devices in the morning and the first place many head to is their chat or messaging app. It has now become both their inbox and their home page. This is an evolution that operators can use to develop Messaging as a Platform propositions.
For users
This enables all sorts of companies to interact with customers in unprecedented ways – travellers, for example, could receive their actual electronic boarding pass securely from airlines rather than receiving an SMS with a link. When on holiday users can order a taxi or Uber, check the weather at their destination and the exchange rate, find a recommended restaurant and book a table and pay for it and learn some handy phrases in another language – all just by sending messages.
For marketers
Further to this progression in customer service and fulfilment, marketers too benefit from Advanced Messaging. They can use read receipts to tell if end-users have read promotional messages and where and when they read them. They can embed call-to-action codes in them, giving access to previously unavailable data to analyse. It all adds up to richer, more engaging advertising content.
For bots
Furthermore, Advanced Messaging also enables Bot-to-Person interactions, where end-user engagements are simply richer and more detailed. The Messaging as a Platform approach and its exponentially increased degree of interaction makes huge new monetization opportunities available to MNOs.
For workplace
Operators can extend their blue sky thinking with Messaging as a Platform; why not a smart, Wi-Fi-enabled video doorbell which uses messaging to record a video message from a visitor when you are not home and ‘chat’ it direct to your mobile device? Built-in AI-based intelligent assistants are great in their place but some people do not like talking out loud to their phone in public places – chatbots can enable that same function via a messaging platform.
Advanced Messaging deployment models: getting it right
Another key benefit of Advanced Messaging is that deployment models can be mixtures of various approaches; operators do not need to commit entirely to a single method and limit their options.
- OWN IMS
PROS
- Retain control of core service
- Flexibility and ability to integrate with other services CONS
- Complex project, requires expertise
- Costly in the short term, CAPEX
- HOSTED SERVICE
PROS
- Pay-as-you-grow model
- Fast deployment and time to market
- Benefit from third-party data centre infrastructure and expertise
- Scope for complementing other services e.g. VoLTE CONS
- Limited service flexibility
- No in-premises deployment option


This is a simple, but friendly, notification.
It will disappear within a few seconds.
This is a simple notification with a brighter color...
If you bring you mouse here you can close it manually.
This is a message telling you that everything is a-okay!
Good job, and good riddance.
This is a notification that something went wrong...
Do you know that you can assign status and relation to a company right in the visit list?
You haven't authorized your LinkedIn account. Would you like some help with that?
With your account connected we can show you what connections you have at a company that visited your site!


About Us
Favorite Stiff One: Dark and Stormy
Favorite Cold One: Princess Diana
Bio: A Native Seattlit who went to college at WSU in Pullman. I enjoying urban hiking, travel, live concerts and learning to code. My favorite drinking game is "A-hole".
Favorite Stiff One: Dale's Pale Ale
Favorite Cold One: Dave Niehaus
Bio: From Bellingham, WA. Went to school for two years in Laramie, WY, then lived and worked in Houston, TX for three years. Favorite drinking game is "Beersbie".
Favorite Stiff One: Old Fashioned
Favorite Cold One: Genghis Khan
Bio: Born in Africa, carried around the world, came to the U.S. when I was nearly five.
Small town life until we moved to Seattle in 2006.Graduated from Garfield Highschool, earned
an assosciates from Seattle Central and studied for two years at the University of Guanajuato in
Guanajuato, Guanajuato, Mexico.
Favorite Stiff One: Mimosa
Favorite Cold One: Jesus Christ
Bio: Born in Honolulu, Hi carried around the world by the U.S. Navy.Raised in a small farm town located in Hamilton, Mt.Graduated from Corvallis Highschool,
and currently persuing a degree in Computer Science.


Basic Button
Enabled
Disabled
Cancel
Approve
Decline
Subscribe
Enabled
Disabled
Cancel
Approve
Decline
Subscribe
Button with Icon
Add
Download
Active Icon
Add
Remove
Accept
Add
Download
Active Icon
Add
Remove
Transparent
Button with Type
Submit
Agree
Decline
Disabled
Transparent
Submit
Agree
Decline
Disabled
Transparent


Adrian
Gomes
heyyy y'all!! oi
~open~
heyy!! its adrian [but u knw dat] n e ways maybe u could hit open pls /if u want/ :) or {for fun} move the circle ; )
hey bestie.. how do i tell you this?? so actually there is nothing here (oops 😬) srry for teasing xx im workin on it! just give me a min, or like a month AAAA idk 😪 well check out my github for now 😅


EVP_KEM-X25519, EVP_KEM-X448 - EVP_KEM X25519 and EVP_KEM X448 keytype and algorithm support
The X25519 and <X448> keytype and its parameters are described in EVP_PKEY-X25519(7). See EVP_PKEY_encapsulate(3) and EVP_PKEY_decapsulate(3) for more info.
The OpenSSL X25519 and X448 Key Encapsulation Mechanisms only support the following operation:
The encapsulate function generates an ephemeral keypair. It produces keymaterial by doing an X25519 or X448 key exchange using the ephemeral private key and a supplied recipient public key. A HKDF operation using the keymaterial and a kem context then produces a shared secret. The shared secret and the ephemeral public key are returned. The decapsulate function uses the recipient private key and the ephemeral public key to produce the same keymaterial, which can then be used to produce the same shared secret. See https://www.rfc-editor.org/rfc/rfc9180.html#name-dh-based-kem-dhkem
This can be set using either EVP_PKEY_CTX_set_kem_op() or EVP_PKEY_CTX_set_params().
Used to specify the key material used for generation of the ephemeral key. This value should not be reused for other purposes. It should have a length of at least 32 for X25519, and 56 for X448. If this value is not set, then a random ikm is used.
EVP_PKEY_CTX_set_kem_op(3), EVP_PKEY_encapsulate(3), EVP_PKEY_decapsulate(3) EVP_KEYMGMT(3), EVP_PKEY(3), provider-keymgmt(7)
This functionality was added in OpenSSL 3.2.
Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at https://www.openssl.org/source/license.html.


Hello! I'm Eduardo (Joey) C. Albano Jr. and this is my webpage. Here you'll find information about me, projects that I'm working on, and ways to contact me.
I graduated from UCSD in 2015 and dropped out of Santa Clara University's School of Law soon after. Since then, I've taken it upon myself to learn programming and computer science to pursue a career in software engineering! I hope to be involved in finance or cryptography -- my dream is to one day design software around cryptocurrencies/blockchain technology.
When I'm not working on things, I love working out (powerlifting), playing games (Melee and DOTA 2 mostly), and eating spicy food. I'm also very interested in Mathematics and languages; right now I'm trying to learn Vietnamese! From time to time I like making music as well, which you can find on my SoundCloud.
As both a part-time gig and hobby, I tutor in Mathematics as well as a variety of standardized tests. You can find more about that here.
My resume can be found here. It's...a work in progress!
I started tutoring in 2014 by helping my college peers with upper division mathematics coursework. I've since branched out to teaching a variety of standardized tests as well. I offer tutoring in the following subjects:
My usual rate is $35/hour for all subjects. All first-time clients get the first hour free of charge.
Feel free to e-mail me if you have any questions or inquiries about tutoring. References and other credentials are available upon request!
| Name | Description | Status |
|---|---|---|
| Jalby.co | This website! | In progress |
| Qustera.com | My quest documentation project | In progress |


The Last Time CO2 Was This High, Humans Didn’t Exist
The last time there was this much carbon dioxide (CO2) in the Earth's atmosphere, modern humans didn't exist. Megatoothed sharks prowled the oceans, the world's seas were up to 100 feet higher than they are today, and the global average surface temperature was up to 11°F warmer than it is now.
As we near the record for the highest CO2 concentration in human history — 400 parts per million — climate scientists worry about where we were then, and where we're rapidly headed now.
According to data gathered at the Mauna Loa Observatory in Hawaii, the 400 ppm mark may briefly be exceeded this month, when CO2 typically hits a seasonal peak in the Northern Hemisphere, although it is more likely to take a couple more years until it stays above that threshold, according to Ralph Keeling, a researcher at the Scripps Institute of Oceanography.
CO2 levels are far higher now than they have been for anytime during the past 800,000 years.
Click image to enlarge. Credit: Scripps Institution of Oceanography.
Keeling is the son of Charles David Keeling, who began the CO2 observations at Mauna Loa in 1958 and for whom the iconic “Keeling Curve” is named.
Carbon dioxide is the most important long-lived global warming gas, and once it is emitted by burning fossil fuels such as coal and oil, a single CO2 molecule can remain in the atmosphere for hundreds of years. Global CO2 emissions reached a record high of 35.6 billion tonnes in 2012, up 2.6 percent from 2011. Carbon dioxide and other greenhouse gases warm the planet by absorbing the sun’s energy and preventing heat from escaping back into space.
The news that CO2 is near 400 ppm for the first time highlights a question that scientists have been investigating using a variety of methods: when was the last time that CO2 levels were this high, and what was the climate like back then?
There is no single, agreed-upon answer to those questions as studies show a wide date range from between 800,000 to 15 million years ago. The most direct evidence comes from tiny bubbles of ancient air trapped in the vast ice sheets of Antarctica. By drilling for ice cores and analyzing the air bubbles, scientists have found that, at no point during at least the past 800,000 years have atmospheric CO2 levels been as high as they are now.
That means that in the entire history of human civilization, CO2 levels have never been this high.
The Keeling Curve, showing CO2 concentrations increasing to near 400 ppm in 2013.
Credit: NOAA.
Other research, though, shows that you have to go back much farther in time, well beyond 800,000 years ago, to find an instance where CO2 was sustained at 400 ppm or greater.
For a 2009 study, published in the journal Science, scientists analyzed shells in deep sea sediments to estimate past CO2 levels, and found that CO2 levels have not been as high as they are now for at least the past 10 to 15 million years, during the Miocene epoch.
“This was a time when global temperatures were substantially warmer than today, and there was very little ice around anywhere on the planet. And so sea level was considerably higher — around 100 feet higher — than it is today,” said Pennsylvania State University climate scientist Michael Mann, in an email conversation. “It is for this reason that some climate scientists, like James Hansen, have argued that even current-day CO2 levels are too high. There is the possibility that we’ve already breached the threshold of truly dangerous human influence on our climate and planet.”
Sea levels are increasing today in response to the warming climate, as ice sheets melt and seas expand due to rising temperatures. Scientists are projecting up to 3 feet or more of global sea level rise by 2100, which would put some coastal cities in peril.
While there have been past periods in Earth's history when temperatures were warmer than they are now, the rate of change that is currently taking place is faster than most of the climate shifts that have occurred in the past, and therefore it will likely be more difficult to adapt to.
A 2011 study in the journal Paleoceanography found that atmospheric CO2 levels may have been comparable to today’s as recently as sometime between 2 and 4.6 million years ago, during the Pliocene epoch, which saw the arrival of Homo habilis, a possible ancestor of modern homo sapiens, and when herds of giant, elephant-like Mastadons roamed North America. Modern human civilization didn’t arrive on the scene until the Holocene Epoch, which began 12,000 years ago.
Regardless of which estimate is correct, it is clear that CO2 levels are now higher than they have ever been in mankind’s history. With global CO2 emissions continuing on an upward trajectory that is likely to put CO2 concentrations above 450 ppm or higher, it is extremely unlikely that the steadily rising shape of the Keeling Curve is going to change anytime soon.
“There's an esthetic to the curve that's beautiful science and troubling reality,” Keeling said. “I'd very much like to see the curve change from going steadily upward to flattening out.”
Related Content
CO2 Emissions Expected to Rise Significantly By 2030
Global Carbon Emissions Hit Record High
Global CO2 Levels Set to Pass 400 ppm Milestone
In the Curve: Monitoring Rising Carbon Emissions


Item. Use redundancy - for example, a particular quality may be represented by both the color and size of a dot. If someone doesn't notice or can't detect one quality, they may be able to detect the other.