text:
# JOOQ-scala-mappingss

All the [JOOQ](http://www.jooq.org) power, in the [scala](http://www.scala-lang.org/) world.

### Why?
-----------

JOOQ is a great tool for accessing SQL stores. It's expressive and powerful. But sometimes you will find yourself building some stuff that could be facilitated for simple use cases. That's the motivation to start this project, using scala macros.

### Installation
------------
Add this definition to the **build.sbt**
```
libraryDependencies ++= Seq(
    "org.jooq"                     %  "jooq"               % "3.6.2",
    "org.jooq"                     %  "jooq-meta"          % "3.6.2",
    "com.github.gabadi.scalajooq" %% "jooq-scala-mappings" % "0.0.3"
)
```
**Important**: Depends on scala 2.11 (there is no scala 2.10 version, at least today), and jooq 3.6.1 or greater with the scala codegen.

### Functionalities
---------------

 1. [Record to entities mappings](#record-to-entity-mapping)
 2. [Entity to record mappings](#entity-to-record-mapping)
 3. [Scala option support](#scala-option-support)
 4. [Implicit type conversion](#implicit-type-conversion)
 5. [Embedded entities](#embedded-entities)
 6. [Base DAO functionality](#base-dao-functionality)
 7. [Base query generator](#base-query-generator)
 8. [One to one / many to one support](#one-to-one-many-to-one-support)

More to come...

### Record to entity mapping

Given this mysql table:
```
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) NOT NULL,
  `last_name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
A mapping to this case class
```
case class User(id: java.lang.Long,
                firstName: String,
                lastName: String) {
}
```
Is as simple as:
```
    val r = dsl.newRecord(Tables.USER)
    r setId 1l
    r setFirstName "Any name"
    r setLastName "Any lastname"

    val meta = com.github.gabadi.scalajooq.JooqMeta.metaOf[tables.User, UserRecord, User]

    val user = meta toEntity r

```
Note: **tables.User** and **UserRecord** were autogenerated by the jooq scala codegen.

Note: To generate the dsl instance, see the JOOQ documentation

This is not magic, this is not reflection, this is a macro.
But what do I win?
The answer is that now, all the runtime exceptions will be compilation exceptions. So, if for example, you have a typo in the user class like this:

```
case class User(id: java.lang.Long,
                firsName: String,
                lastName: String) {
}
```
During compilation you'll see a message like this:

```
Mappings error:
 com.github.gabadi.scalajooq.User.firsName expects a db.test.public.tables.records.UserRecord.FIRS_NAME column, but doesn't exists
```

### Entity to record mapping
The other way is valid too
```
    val entity = User(0, "name", "last")

    val meta = com.github.gabadi.scalajooq.JooqMeta.metaOf[tables.User, UserRecord, User]

    val record = meta toRecord entity
    record.store()

```
Note: This the method toRecord depends in an implicit DSLContext instance

### Scala option support
Option values, one important feature in scala, is not supported for JOOQ until version 4.0. But with JOOQ-scala-mapping, giving this class:
```
case class UserOption(id: java.lang.Long,
                      firstName: Option[String],
                      lastName: Option[String]) {
}
```
Anyone can make a mapping like this:

```
    val r = dsl.newRecord(Tables.USER)
    r setId 1l

    val meta = com.github.gabadi.scalajooq.JooqMeta.metaOf[tables.User, UserRecord, User]

    val user = meta toEntity r
    println(user)
```
With this result:
```
    User(1, None, None)
```
And in the other hand, JOOQ-scala-mappings will never let you have an Entity with a null field. Instead of that, an exception will be thrown when you try to generate that entity.

###Implicit type conversion
The current user as defined, has a small issue. If you see the id field, you'll see that it's not a scala Long, it's a java Long.
So, what if you want a standard scala **Long**?, or **Int**? or **Boolean**?
For that, you have implicit conversions. That means that for **JOOQ-scala-mappings** this two entities are valid representations for the **user** table

```
case class User1(id: java.lang.Long,
                 firsName: String,
                 lastName: String) {
}
case class User2(id: Long,
                 firsName: String,
                 lastName: String) {
}

```

###Embedded entities
Ok, you need to represent a complex entity, with some other embedded entity inside...
Something like this:

```
case class Name(first: String, last: String)

case class Profile(name: Name)

case class FullUser(id: Long, profile: Profile)
```

This can be automatically mapped to a table like this:
```
CREATE TABLE `full_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `profile_name_first` varchar(50),
  `profile_name_last` varchar(50),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
See that the **FullUser** has an **Id** and we can call the **Profile** an embedded entity inside the **FullUser**, and the **Name** inside the **Profile** may be another embedded entity.

And that hierarchy can be mapped with something like this:
```
 val nameMeta = JooqMeta.namespacedMetaOf[tables.FullUser, FullUserRecord, Name]("profileName")
 val profileMeta = JooqMeta.namespacedMetaOf[tables.FullUser, FullUserRecord, Profile]("profile")
 val userMeta = JooqMeta.metaOf[tables.FullUser, FullUserRecord, FullUser]
```
Where the **namespacedMetaOf** does the magic
If this seams to be too much work, we can simple do:
```
 val userMeta = JooqMeta.metaOf[tables.FullUser, FullUserRecord, FullUser]
```
And with only that, all the other macros will be auto generated.

###Base DAO functionality
Now, it could be nice to have the most basic functionalities already implemented. For that there is a DAO with the most necessary methods. The usage is as simple as:
```
  implicit lazy val userMeta = JooqMeta.metaOf[tables.User, UserRecord, User]

  lazy val userDAO = new DefaultJooqDAO[UserRecord, User]() {}
```
By doing so, you will have this operations already implemented:
```
findAll(): List[User]
insert(user: User): Long
insert(user: User, more: User*): Unit
insertAll(users: Seq[User]): Unit
update(user: User): Int
update(user: User, more: User*): Int
updateAll(users: Seq[User]): Int
delete(user: User): Int
delete(user: User, more: User*): Int
deleteAll(users: Seq[User]): Int
deleteAll(): Int
deleteById(id: Long): Int
deleteById(id: Long, more: Long*): Int
deleteByIds(ids: Seq[Long]): Int
findById(id: Long): Option[User]
findByIds(id: Long, more: Long*): List[User]
findByIds(ids: Seq[Long]): List[User]
```
This dao implementation, works for entities with a single **primaryKey**, with type **Long** or **Int** and **autoincremental**.
In case of, for example, a **String** **primaryKey**, can be resolved with:

```
  implicit lazy val userMeta = JooqMeta.metaOf[tables.UserByCode, UserByCodeRecord, UserByCode]

  lazy val userDAO = new JooqDAO[UserByCodeRecord, String, UserByCode]() {}
```
Where the second type parameter in the **JooqDAO** indicates that this table has a **String** as a **primaryKey**.

Another use case, is that the **User.id** is not autogenerated, for example an **UUID**. In that case, this can resolved simply doing
```
  implicit lazy val userMeta = JooqMeta.metaOf[tables.User, UserRecord, User]

  lazy val userDAO = new DefaultJooqDAO[UserRecord, User]() {
    override lazy val createFields = userMeta.fields
  }
```
This means: During creation, use all the fields of the user. Does not ignore the **primaryKey** like the default implementation.

Another use case, may be enhanced functionality, like a **saveOrUpdate** that depends on the SQL implementation.
 This is an extension for **saveOrUpdate** in a **MySQL** store

```
  class MySQLDefaultDAO [Rec <: UpdatableRecord[Rec], Entity] extends DefaultJooqDAO[Rec, Entity] {
    def saveOrUpdate(e: Entity)(implicit dsl: DSLContext): Unit = {
      val createRecord = attached(e)
      val updateRecord = attached(e).into(updateFields :_*)
      dsl.insertInto(table).set(createRecord).onDuplicateKeyUpdate().set(updateRecord).execute()
    }

    def saveOrUpdate(e: Seq[Entity])(implicit dsl: DSLContext): Unit = e.foreach(saveOrUpdate)

    def saveOrUpdate(e: Entity, en: Entity*)(implicit dsl: DSLContext): Unit = saveOrUpdate(en :+ e)
  }
```
Now all the DAOs that extends **MySQLDefaultDAO** instead of **DefaultJooqDAO** will have the **saveOrUpdate** functionality.

**Important Note:**

All the methods definitions in the default dao, actually receives one more implicit parameter. That parameter is the **Jooq DSLContext** used for the dao operations. So the whole usage example should be:
```
    val configuration = new DefaultConfiguration()
      ...
    implicit val dsl = DSL using configuration
      ...
    userDAO insert User(0l, "name", "last")
```
###Base query generator
This feature is trivial in the beginning, but combined with the one-to-one, many-to-one, etc support, may be very powerful.

With this, a query maybe autogenerated. So, for example:
```
  val userMeta = JooqMeta.metaOf[tables.User, UserRecord, User]
  println(userMeta.query)
```
Generates this code:
```
select
  "PUBLIC"."USER"."ID",
  "PUBLIC"."USER"."FIRST_NAME",
  "PUBLIC"."USER"."LAST_NAME"
from "PUBLIC"."USER"
```
**NOTE:** This will autogenerate the joins for the x-to-x support
###One to one / many to one support
With this feature, it's possible to fetch eagerly a joined entity.

For example, giving this schema:
```
CREATE TABLE `city` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `state_id` bigint(20),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `state` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `country_id` bigint(20),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `country` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
This can be mapped with this entities and mappers
```
case class City(id: Long, name: String, state: State)

case class State(id: Long, name: String, country: Country)

case class Country(id: Long, name: String)

...

implicit lazy val countryMeta = JooqMeta.metaOf[tables.Country, CountryRecord, Country]
implicit lazy val stateMeta = JooqMeta.metaOf[tables.State, StateRecord, State]
implicit lazy val cityMeta = JooqMeta.metaOf[tables.City, CityRecord, City]
```
This **JooqMetas** may be used with the **JooqDAOs**, or simply doing:
```
   println(cityMeta.query)
```
will be autogenerated the following query
```
select
  "PUBLIC"."CITY"."ID",
  "PUBLIC"."CITY"."NAME",
  "PUBLIC"."STATE"."ID",
  "PUBLIC"."STATE"."NAME",
  "PUBLIC"."COUNTRY"."ID",
  "PUBLIC"."COUNTRY"."NAME",
  "PUBLIC"."STATE"."COUNTRY_ID",
  "PUBLIC"."CITY"."STATE_ID"
from "PUBLIC"."CITY"
  join "PUBLIC"."STATE"
  on "PUBLIC"."CITY"."STATE_ID" = "PUBLIC"."STATE"."ID"
  join "PUBLIC"."COUNTRY"
  on "PUBLIC"."STATE"."COUNTRY_ID" = "PUBLIC"."COUNTRY"."ID"
```
**IMPORTANT:** Only the fetching is done eagerly, but there is no cascade functionality.

###Next functionalities
--------

 1. Custom join field
 2. Many to many functionality
 3. Basic query generator

###Limitations
------------

 1. Does not support a two way relation. Something like this:
```
case class Profile(firstName: String, lastName: String)

case class User(id: Long, profile: Profile)
```
In this case, the **User** knowns the **Profile**. And the **Profile** knowns the **User**. So the macro can never be resolved.
 2. The current version, does not support an the same entity to be referenced twice in the same entity, like in this example.
```
case class City(id: Long, name: String)

case class Route(from: City, to: City)
```

###Contributing
------------
Please see [CONTRIBUTING](CONTRIBUTING.md)

###Contributors
------------

* **[Ricardo Tellechea](https://www.linkedin.com/in/ricardotellechea)**

repository: gabadi/JOOQ-scala-mappings

repo_name: gabadi/JOOQ-scala-mappings


text:
# Wickr Webhook Bot

This project is a WickrIO integration created via [cookiecutter-wickr-bot](https://github.com/WickrInc/cookiecutter-wickr-bot)

## Installation

See the WickrIO [Getting Started Guide](https://wickrinc.github.io/wickrio-docs/#wickr-io-getting-started).

## Usage

Webhook Bot understands the following commands:

 - `/help` - Prints a help message with all available commands
 - `/show` - Show the webhook URL for the current room
 - `/rekey` - Rotate the current webhook URL for the room

### Sending a webhook message

The API is almost identical to the [Slack Incoming Webhooks API](https://api.slack.com/messaging/webhooks#posting_with_webhooks).

``` bash
curl https://hooks.example.com/send/$KEY -d 'payload={"text": "hello world"}'
# or
curl https://hooks.example.com/send/$KEY -H "Content-type: application/json" -d '{"text": "hello world"}'
```

It also accepts webhooks in the [AWS Chime](https://github.com/awsdocs/amazon-chime-developer-guide/blob/master/doc_source/webhooks.md) format:

``` bash
curl https://hooks.example.com/send/$KEY -H "Content-type: application/json" -d '{"Content": "hello world"}'
```

## Development

### Building

Run `make` to create a new `software.tar.gz` package, which can be installed as a WickrIO Custom Integration. See the [WickrIO docs](https://wickrinc.github.io/wickrio-docs/#developing-integrations-creating-an-integration-locally) for more details.

# License

This software is distributed under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)

```
   Copyright 2021 Wickr, Inc.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
```

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
# MongoIce
An entity framework-like library for MongoDB

## Features

This library allows to create collections and indexes automatically based on a context decorated with some entity framework-like attributes.
It allows also some additional helpers like collections cleanup.
It's work in progress!

## Usage

Model definition and description:

```c#
public class Comment
{
  [BsonId]
  [BsonRepresentation(BsonType.ObjectId)]
  public string Id { get; set; }

  [IndexDescriptor(IndexType.Ascending, true, false, false)]
  public long Timestamp { get; set; }

  public string AuthorName { get; set; }

  public string Content { get; set; }
}

public class MongoContext : BaseDocumentContext
{
  /// <summary>
  /// Comment collection
  /// </summary>
  [CollectionDescriptor("Comments", typeof(Comment))]
  public IMongoCollection<Comment> Comments { get; set; }

  public MongoContext(string serverUrl, string databaseName) : base(serverUrl, databaseName)
  {

  }

  public override void CreateIndexes()
  {
    base.Database.CreateIndex<Comment>(this.Comments);
  }
}
```

Context usage:

```c#
using (var context = new MongoContext("mongodb://localhost:27017", "MongoIceTestDatabase"))
{
  // perform all collection specific operation using linq and mongodb features

  context.Comments.DeleteMany(x => x.Id != null);
}
```

license: MIT

repository: mingditts/MongoIce

gha_language: C#

gha_license_id: MIT

repo_name: mingditts/MongoIce


text:
---
title: InterSpecialization Specializing
date: 2013-09-01 23:01:29 -07:00
layout: post
type: post
parent_id: '0'
password: ''
status: publish
meta:
  _edit_last: '44242401'
  _publicize_pending: '1'
author:
  login: bzreinhardt
  email<EMAIL_ADDRESS>  display_name: Ben
  first_name: Ben
  last_name: Reinhardt
---

Specialization: the concept, in the context of trade from the excellent EconTalk Monologue hit me very personally.

 Trade (in ideas and goods) both benefits from and encourages us to become even more intensely specialized. I wondered ‘where do I fit into this? Am I in trouble?’

 I’m not intensely specialized in one area – in my job I have to deal with everything from Maxwell’s equations to microcontrollers, from programming languages to power supplies. And my hobbies span practicing cartwheels to reading articles about the political economy of recycling. There isn’t one area in which I would say I’m a specialist.

 I used to think this made me inferior to someone whose knowledge was intensely focused in a single area. However, a conversation with a Caltech friend dispersed this illusion. Thanks to the broad science background that Caltech gave both of us, he (a software engineer) could easily communicate to me (a mechanical engineer) a neurological process with far more detail than one would expect, given our nominal backgrounds.

 My realization is that a world filled with intensely specialized people needs people who specialize in facilitating communication between the specialists. In order to fuse ideas from opposite ends of the discipline-spectrum, one can’t have your head too deep in any single ostrich hole. That in and of itself is a type of specialization.

gha_language: HTML


text:
# factorio-types

Typescript declarations for the factorio mod API. Note this library is not particularly "battle-hardened" by real use, but is here for anyone that may get value from it.

Install `factorio-types` from [npm](https://www.npmjs.com/package/factorio-types), but note the warning above about minimal testing.

Intended to be used with [Typescript to Lua](https://github.com/TypeScriptToLua/TypeScriptToLua).

A very minimal proof-of-concept showing basic toolchain setup can be found [Here](https://github.com/sguest/factorio-fire-armor-typescript)

branch_name: refs/heads/main


text:
# Configuration

Heartbeat is configured in its own section in the app configuration file.

Required fields

- host and port of the popcorn server
- node_role and node_version of the current node

Optional fields

- metrics are a list of named and typed metrics, each with a callback module/function

```erlang
{popcorn_heartbeat_erlang, [
       {host, "<IP_ADDRESS>"},
       {port, 9125},
       {node_role,    "xmpp"},
       {node_version, "1.2.3"},
       {metrics, [
           [{name, "memory"}, {type, guage}, {module, popcorn_heartbeat_util}, {function, memory_used}]
       ]}
]}
```

# Testing

```erlang
application:start(popcorn_heartbeat_erlang), timer:sleep(1000), application:stop(popcorn_heartbeat_erlang).
```


text:
---
layout: post
title: "Ditching full frame for mirrorless…"
microblog: false
date: 2017-10-30 21:30 +0300
guid: http://desparoz.micro.blog/2017/10/30/ditching-full-frame.html
---
I really like this take on why mirrorless is a better option, at least for the photographer in question.

[www.youtube.com/watch](https://www.youtube.com/watch?v=oUStdxaf-FE&feature=share)

Interesting that the photographer, James Popsys, believes that he takes better photos with mirrorless, mainly due to be inspired to take photos more often.

I tend to agree. I went through a similar journey, and have been all in on mirrorless for a few years now.


text:
# Setup
This document describes the steps that went into setting up the database.

I am familiar with [CouchApp][couchapp]. This is a python app specifically written for Python 2, which is End-Of-Life.
Besides that, it also can't handle defining users, as can be seen from [this issue][couchapp:issue]. So I wanted to look at other tools and found [jo's best practices][jo].

## Tools
I started installing the tools with the following command

```plain
> npm install --global couchdb-bootstrap couchdb-compile couchdb-configure couchdb-ensure couchdb-push couchdb-secure
```

## Database
I create a database for my local CouchDB instance with the `couchdb-ensure` command

```plain
> couchdb-ensure http://admin:password@localhost:5984/shortener
```

which responded with

```json
{
  "ok": true
}
```

## Compile Design Document
Next a created a directory stucture adhering [the couchapp structure][structure].

```plain
├── short
    ├── _id
    └── views
        └── events
            └── map.js
```

and used `couchdb-compile short` and got the following output

```json
{
  "_id": "_design/short",
  "views": {
    "events": {
      "map": "function(doc) {\n    if (doc.type === 'creation') {\n        emit([doc.short, doc.type], { type: doc.type, url: doc.url });\n    }\n    if (doc.type === 'retrieve') {\n        emit([doc.short, doc.type], 1);\n    }\n}"
    }
  }
}
```

## Pushing to the database
The previous step was not necessary since the `couchdb-push` command can also push the same directory structure. I did end up using the compiled design document.

```plain
couchdb-push http://admin:password@localhost:5984/shortener short_ddoc.json
```

Which returned

```json
{
  "ok": true,
  "id": "_design/short",
  "rev": "1-c16243e9fc0b4761b20444ecc00a23e7"
}
```

[couchapp]: https://github.com/couchapp/couchapp
[couchapp:issue]: https://github.com/couchapp/couchapp/issues/126
[jo]: https://github.com/jo/couchdb-best-practices
[structure]: https://github.com/couchapp/couchapp/wiki/Complete-Filesystem-to-Design-Doc-Mapping-Example

repository: fifth-postulate/shortener

repo_name: fifth-postulate/shortener


text:
# once_per_worker

`once_per_worker` is a utility to create [dask.delayed](https://docs.dask.org/en/latest/delayed.html) objects around functions that you only want to ever run once per [distributed](https://distributed.dask.org/en/latest/) worker.

Say you have some large data baked into your docker image (so every worker already has a copy of it). You need to use that data as auxiliary input to another dask operation (`df.map_partitions`, for example). But parsing/preprocessing the data is slow, and once loaded into memory, the data is large, so it's faster for each worker to load the data from disk than to transfer the serialized data between workers in the cluster. So you only want to call the parsing function once per worker, then use the same parsed object per worker in all downstream tasks.

By wrapping your preprocessing function in `once_per_worker`, you get a Delayed object that, on a given worker, will always resolve to the same pre-processed object. Your function is called the first time you _access an attribute_ on the returned value.

## Example

```python
# example.py
import os
import time

class SlowDataLoader:
    def __init__(self, x):
        print(f"Very slowly loading the data on PID {os.getpid()}")
        time.sleep(x)
        self.x = x

    def value(self):
        print(f"SlowDataLoader is {hex(id(self))} on PID {os.getpid()}")
        return self.x

    def __getstate__(self):
        raise RuntimeError("Don't pickle me!")

if __name__ == "__main__":
    import dask
    import distributed
    from once_per_worker import once_per_worker

    ddf = dask.datasets.timeseries()

    loaded_slow_loader = once_per_worker(lambda: SlowDataLoader(3))
    # ^ this is a dask.Delayed object that will resolve to `SlowDataLoader(3)` on each worker

    ddf = ddf.map_partitions(
        lambda df, loader: df.assign(name=df.name + str(loader.value())),
        # ^ NOTE: `SlowDataLoader(3)` isn't created until the `loader.value` attribute access here
        loaded_slow_loader,
        meta=ddf,
    )

    client = distributed.Client(processes=True)
    print(client)
    print(ddf.compute())
```

```shell
$ python example.py
<Client: 'tcp://<IP_ADDRESS>:59309' processes=4 threads=16, memory=32.00 GiB>
Very slowly loading the data on PID 25799
Very slowly loading the data on PID 25800
Very slowly loading the data on PID 25801
Very slowly loading the data on PID 25802
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x1268e15e0 on PID 25800
SlowDataLoader is 0x1276becd0 on PID 25801
SlowDataLoader is 0x1276becd0 on PID 25801
SlowDataLoader is 0x1276becd0 on PID 25801
SlowDataLoader is 0x126aa7400 on PID 25802
SlowDataLoader is 0x126aa7400 on PID 25802
SlowDataLoader is 0x1268e15e0 on PID 25800
SlowDataLoader is 0x126aa7400 on PID 25802
SlowDataLoader is 0x1268e15e0 on PID 25800
SlowDataLoader is 0x1268e15e0 on PID 25800
SlowDataLoader is 0x126aa7400 on PID 25802
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x1276becd0 on PID 25801
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
SlowDataLoader is 0x11a8eed00 on PID 25799
                       id       name         x         y
timestamp
2000-01-01 00:00:00  1002     Jerry3 -0.094005  0.274997
2000-01-01 00:00:01   941  Patricia3 -0.246477  0.668154
2000-01-01 00:00:02   998       Bob3  0.255090  0.912544
2000-01-01 00:00:03  1013     Edith3  0.049940 -0.412688
2000-01-01 00:00:04  1008       Ray3  0.532393 -0.389245
...                   ...        ...       ...       ...
2000-01-30 23:59:55   997    Ingrid3  0.462019 -0.642151
2000-01-30 23:59:56  1054  Patricia3  0.030638  0.648196
2000-01-30 23:59:57  1062     Kevin3 -0.798188  0.480087
2000-01-30 23:59:58  1027    Ingrid3 -0.541842 -0.571846
2000-01-30 23:59:59   981     Jerry3 -0.564332 -0.217744
[2592000 rows x 4 columns]
```

## Installation

```
python -m pip install git+https://github.com/gjoseph92/once-per-worker.git
```

## Issues

This package is a bit of a hack.

* We don't take advantage of parallelism as much as possible: your delayed function isn't called until some other task accesses an attribute on it. Basically, we wait to call the function until right when it's needed, instead of calling it in advance so the data is already ready by the time it's needed.
* The data-loading function doesn't show up as its own task, so on the dashboard, whatever task accesses it will appear to take a very long time (because it's actually loading the data).
* You have to access an attribute on the object returned by your function for anything to actually happen.


text:
---
title: Christ in Song - 581-590
metadata:
    description: |
        Christ in Song - 581-590
    keywords:  |
        Christ in Song, adventhymnals, advent hymnals, 581-590
    author: Brian Onang'o
---

#### Advent Hymnals
## Christ in Song - 581-590

# Index of Titles
# | Title
-- |-------------
581|[Angry Words!  Oh, Let Them Never](/christ-in-song/501-600/581-590/Angry-Words!-Oh,-Let-Them-Never)
582|[Tell It Again](/christ-in-song/501-600/581-590/Tell-It-Again)
583|[Bringing in the Sheaves](/christ-in-song/501-600/581-590/Bringing-in-the-Sheaves)
584|[Peace, Be Still!](/christ-in-song/501-600/581-590/Peace,-Be-Still!)
585|[Away the Bowl!](/christ-in-song/501-600/581-590/Away-the-Bowl!)
586|[Look for the Way-Marks](/christ-in-song/501-600/581-590/Look-for-the-Way-Marks)
587|[The Temperance Call](/christ-in-song/501-600/581-590/The-Temperance-Call)
588|[Harvest Time](/christ-in-song/501-600/581-590/Harvest-Time)
589|[Hasten On, Glad Day](/christ-in-song/501-600/581-590/Hasten-On,-Glad-Day)
590|[Man the Life-Boat!](/christ-in-song/501-600/581-590/Man-the-Life-Boat!)

repository: GospelSounders/adventhymnals

repo_name: GospelSounders/adventhymnals


text:
# 24-7-stage

## a bot for [Nugget development™](https://discord.gg/Z4ebH8PXeA) server

# what does the bot do?
it plays music 24/7 in a stage channel. Can be played via a livestream or a youtube playlist

# how to run?
- copy the content of .env.example
- create a `.env` file and paste it
- fill in the credentials
- install dependencies
- run the bot

join the support server for support


text:
debugpy is an implementation of the Debug Adapter Protocol for Python.

The source code and the issue tracker is [hosted on GitHub](https://github.com/microsoft/debugpy/).

repository: microsoft/debugpy

gha_language: Python

gha_license_id: NOASSERTION

repo_name: microsoft/debugpy


text:
---
date_published: '2021-07-07'
date_modified: '2021-08-24'
---

Using secret recovery phrases is not recommended, as they are [insecure](https://medium.com/mycrypto/a-safer-mycrypto-79d65196e7d8). If you were to access your account on a phishing site with a private key, the phishers would get full access to your wallet. However, if you still desire to create and use a wallet in this manner, you can generate them locally with the [MyCrypto Desktop App](https://download.mycrypto.com/).

What kind of issue are you experiencing?

repository: MyCryptoHQ/knowledge-base-content

gha_language: TypeScript

repo_name: MyCryptoHQ/knowledge-base-content


text:
## Goals of the app/site
#### short-term
####long-term

## Target Audience
The target audience of REPO is ...

#### User type 1:
* What we know about them: A short statement about the user
* User 1's goals:
    * A bulleted list of user objectives

#### User type 2:
* What we know about them: A short statement about the user
* User 1's goals:
    * A bulleted list of user objectives

## Competitors
List other apps that serve this segment and this need
#### What does this do better/worse than competitors?
* bulleted list of pros and cons of the competition

## Type of work needed

- [ ] Branding
- [ ] Logo Design
- [ ] Icon Design
- [ ] Font Design
- [ ] Website Design
- [ ] Interface Design
- [ ] Wireframes & User Flows
- [ ] Usability & User Testing
- [ ] Documentation Readability

## How to contribute
Directions on where to put files, issues and a link to the dev CONTRIB document

repository: anthonycuellar/Design-Brief

repo_name: anthonycuellar/Design-Brief


text:
Common Issue: "Gathering Facts" is *really slow* (FQDN lookup problem)
==============================================================================

Like, 30 seconds kind of slow..!

I've encountered this when the system hostname is *not fully-qualified*, resulting in a DNS query (that seemingly times out after - you guessed it - 30 seconds) in attempt to figure out the hosts' Fully-Qualified Domain Name (FQDN).

The culprit in this case is a call to Python's `socket.getfqdn()`, which can be found when Ansible is gathering the `platform` facts at

<https://github.com/ansible/ansible/blob/v<IP_ADDRESS>-1/lib/ansible/module_utils/facts/system/platform.py#L49>

You can test if this is an issue with the following terminal command:

    time python -c 'import socket; print(socket.getfqdn())'

You want that to return really quickly, and should see something like:

    $ time python -c 'import socket; print(socket.getfqdn())'
    nrser-mbp.local

    real	0m0.394s
    user	0m0.015s
    sys	0m0.021s

If it obviously takes a long time and you see result more like

    $ time python -c 'import socket; print(socket.getfqdn())'
    nrser-mbp

    real	0m30.028s
    user	0m0.013s
    sys	0m0.008s

then it's definitely a problem and is **single-handedly slowing fact gathering to a crawl**.

The reason it's happening is because the system's `HostName` is not fully-qualified - notice the `nrser-mbp.local` output in the fast time and the `nrser-mbp` in the slow one.

The remedy is to add the `.local` to the `HostName`:

    sudo scutil --set HostName "$(scutil --get LocalHostName).local"

and you're all set!

> This assumes you get something reasonable out of `scutil --get LocalHostName`... you can of course just manually stick your hostname in there too.

If you have a specific hostname/network setup where `.local` doesn't make sense, you're of course going to have to do something more complicated, probably involving your local DNS resolution and/or network DNS, but the basic idea remains: get `socket.getfqdn()` to go fast.

Credit where credit is due:

1.  https://apple.stackexchange.com/questions/175320/why-is-my-hostname-resolution-taking-so-long

repository: nrser/qb

gha_language: Ruby

repo_name: nrser/qb


text:
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
- Uses flask `before_request` to protect all endpoints rather than protecting routes present at instantiation time

## [2.0.0] - 2023-03-10
### Removed
Removed obsolete `PlotlyAuth`. `dash-auth` is now just responsible for `BasicAuth`.
Drop Python 2 support. Minimum Python version is now 3.6.

## [1.4.1] - 2019-10-04
### Fixed
Fixed a bug with PlotlyAuth not properly converting user data to json

## [1.4.0] - 2019-09-02
### Changed
Updated to require dash 1.x - this did not affect the API of this package at all, but usage examples and tests were adapted for the dash API changes.

## [1.3.2] - 2018-12-18
### Change
Changed basic-auth to use a dictionary of valid credentials, rather than lists.
This ensures only one valid password per user, and credential checks are faster.

## [1.3.1] - 2018-12-05
### Changed
Changed the deprecation notice to only 2 repos (`dash-basic-auth` and `dash-enterprise-auth`).
The oauth abstraction can still be used with dash-auth.

## [1.3.0] - 2018-12-04

Add integrations with Dash Deployment Server 2.6. [#75](https://github.com/plotly/dash-auth/pull/75)
This version works on both 2.5 and 2.6.

dash-auth will be split into 2 repositories:

- `dash-basic-auth` -> basic_auth
- `dash-enterprise-auth` -> Dash Deployment Server integration, replace PlotlyAuth.

### Added
- Pending deprecation notice for PlotlyAuth.

### Changed
- Logout button changed to a `dcc.LogoutButton` if app is on Dash Deployment Server 2.6
- `get_username` from request headers if app is on Dash Deployment Server 2.6
- Disabled authentication if app is on Dash Deployment Server>=2.6, authentication is now performed on the Dash Deployment Server for all deployed apps.

### Fixed
- Fixed logout invalidation url and put in a try/catch so the token is still cleared from the cookies after an error.

## [1.2.0] - 2018-10-11
### Fixed
- Kerberos tickets can be retrieved from a Dash Deployment Server and used
to perform multi-hop authentication. [#64](https://github.com/plotly/dash-auth/pull/64)

## [1.1.4] - 2018-09-11
### Fixed
- Token invalidation from self signed on-prem. [#56](https://github.com/plotly/dash-auth/pull/56)
- Logout button redirect to app url. [#56](https://github.com/plotly/dash-auth/pull/56)
- Cookie clear use `requests_pathname_prefix`. [#56](https://github.com/plotly/dash-auth/pull/56)

## [1.1.3] - 2018-09-12
### Fixed
- Detect requests coming from orca pdf generation and disable unsupported secure cookies. [#60](https://github.com/plotly/dash-auth/pull/60)

## [1.1.2] - 2018-08-15
### Fixed
- Remove trailing slash from the cookie path.

## [1.1.1] - 2018-08-14
### Fixed
- Cookies path take `requests_pathname_prefix` instead of `routes`. [#54](https://github.com/plotly/dash-auth/pull/54)
- Ensure failed cookie unsign clear the cookies.

## [1.1.0] - 2018-08-10
### Added
- Added `get_username` to `PlotlyAuth`, signed cookie stored in `USERNAME_COOKIE`.
- Added `get_user_data` to `PlotlyAuth`, custom cookie that can contains any json data for the user.
- Added `logout` to `PlotlyAuth`, helper method to remove the auth cookies and invalidate the token.
- Added `create_logout_button` which create a dash logout button that will logout on click to be inserted in the layout.

## [1.0.2] - 2018-05-31
### Fixed
- Use update_or_create for OAuth app creation when available, to avoid
  race condition.

## [1.0.1] - 2018-05-02
### Fixed
- Handle the case where more than one OAuth app exists in streambed.

## [1.0.0] - 2018-04-11
### Added
- `PlotlyAuth` now supports "secret" authentication using the `share_key`
parameter.

### Changed
- All `Auth` subclasses must now implement `index_auth_wrapper()`. See
`basic_auth.py` for an example that preserves the existing behaviour.

## [0.1.0] - 2018-03-27
### Added
- `PlotlyAuth` now supports multiple URLs. Supply a localhost URL and a remote
URL in order to test your Plotly login on your local machine while keeping
the login screen available in your deployed app. Usage:
```
dash_auth.PlotlyAuth(app, 'my-app', 'private', [
    'https://my-deployed-dash-app.com',
    'http://localhost:8050'
])
```
See https://github.com/plotly/dash-auth/pull/29

### Fixed
- `PlotlyAuth` is now stateless. This allows `PlotlyAuth` to be
used in Dash Apps that are deployed with multiple workers.
See https://github.com/plotly/dash-auth/pull/32

## [0.0.11] - 2018-02-01
### Added
- Added logging on request failure for the `PlotlyAuth` handler
- Added retry logic for the `PlotlyAuth` handler

## [0.0.10] - 2017-10-05
### Fixed
- The oauth redirect URL is now trailing-backslash insensitive

## [0.0.9] - 2017-10-02
### Fixed
- Allow the version to be imported with `dash_auth.__version__`

## [0.0.8] - 2017-09-26
### Fixed
- Wrap string responses in a `flask.Response` so that cookies can be added to it

## [0.0.7] - 2017-09-19
### Fixed
- Fixed authentication with path based routing with dash==0.18.3
### Added
- Add path and secure attributes to the plotly auth cookies for `PlotlyAuth`
### Removed
- No longer implicitly saves `localhost:8050` as a valid oauth redirect URL for `PlotlyAuth`

## [0.0.6] - 2017-09-05
### Fixed
- Path-based routing with Plotly auth for apps where `app.config.requests_pathname_prefix` is not `/` now works

## [0.0.5] - 2017-08-22
### Added
- Python 3 support for Basic Auth

## [0.0.4] - 2017-08-17
### Added
- Integration and continuous integration tests
- Python 3 support for Plotly Auth

## [0.0.4rc7] - 2017-08-09
First stable Python 2 release

repository: plotly/dash-auth

repo_name: plotly/dash-auth


text:
# How to Report an Issue with a Bot or Request a New Feature

Have you used a bot that should be improved?
This guide helps you report bugs and communicate ideas for new features.

Improving a bot starts with documenting the scenario(s) in which we want the bot to behave differently than it did so far. This applies to both fixing bugs and adding features.

These scenarios are the fuel for bot development. Developing bots is very much an incremental process. A bot evolves as we collect more scenarios describing the desired behavior.

Explaining your use-case in human language is a good start, but a developer will usually ask for more data.

## Session Recording and Archive

The most common way to describe your scenario or use-case is to share a recording of a play session using the bot.

The artifact of the session recording allows us to:

+ See which bot program was used in the session and how it was configured (including bot-settings).
+ Travel back in time and see what the bot saw in the past.
+ Understand why our bot did what it did.
+ Create simulation environments to test new bot programs: https://to.botlab.org/guide/testing-a-bot-using-simulated-environments
+ Extract training data used to adapt bot program codes to new users and their setups.

In summary, sharing a session recording is a fast and efficient way to answer many questions from people who want to help you.

### Getting the Session Recording Archive

How do you get a session recording that you can share with others?

By default, the BotLab client automatically creates that recording every time you run a bot. That means saving the session recording is already taken care of unless you chose to disable it for that session.

(If you have set the `--detailed-session-recording` switch to `off` on a session, the recording will not be available for that session)

To export a recording after running a bot, we use the `Devtools` in the BotLab client:

![Opening DevTools from the main menu](./image/2021-12-09-botlab-client-main-menu-enter-devtools.png)

A button in the main menu brings us into the `Devtools` view:

![DevTools view in the botlab client](./image/2021-12-09-botlab-client-devtools-default.png)

Here we see a link to a web page on the `localhost` domain. Clicking that link brings opens a web browser. The actual graphical user interface for the Devtools is on this web page.

![DevTools - choose a session to inspect](./image/2021-12-09-botlab-devtools-select-session.png)

You find a list of recent play sessions on that web page, the last one at the top.

When you run a bot, the BotLab client window also displays the session's name, so you can find it again in this list later, even if you started other sessions in the meantime.

Clicking on one of the sessions' names brings us into the view of this particular session:

![DevTools - initial view of a session](./image/2021-12-09-botlab-devtools-session-summary.png)

To export the session recording, use the `Download session recording archive` button. This gets you a zip archive that you can then share with other people. Now you can get help from other developers for your exact situation, no matter if the solution requires a change in program code or just different bot-settings.

### Inspecting a Session and Identifying the Time of Interest

Besides the session archive, a developer might ask you at which time the bot should have behaved differently. The longer the session, the more likely you will be asked to clarify this.

A precise way to communicate the time range of interest is to note the events indices for this range. Each action that a bot sends to a game client belongs to one event in the session timeline.

In the session view, there is a timeline of events in that session. The events are numbered so that we can identify them; each has its index.

A play session can easily contain thousands of events, and we want to find out what subsequence of events is related to the current problem or feature request.

Clicking on an event in the timeline opens the details for this event. Here you can see what the game looked like at that time and what the bot did. The event details contain the complete bot's response to this event, including the inputs to send to a game client.

![DevTools - view of play session event details](./image/2021-12-09-botlab-devtools-session-event-details.png)

Bot authors often use the status text to inform about what action the bot takes and how it decided to prefer this action. The bot generates a new status text for each event. The status texts for consecutive events can be very similar or even the same, especially if the bot was waiting for a process in the game to complete and did not take any action in the event.

repository: Viir/bots

gha_language: Elm

repo_name: Viir/bots


text:
#### STEEMBLR GOALS AND VALUES
Steemblr is an open-source micro-blogging media app based on the steem blockchain. Steemblr has no direct reward pattern, but uses Steemit as a front-end for the steem users on the platform.

## GOALS

Steemblr supports both steem and non-steem users registration and activities on the platform. It aims at creating an ecosystem where both steem and non-steem users can co-habit in a social environment. It focuses on creating a decentralized and uncensored platform where users can blog about almost anything including quotes.

Steemblr also aims at creating an environment where non-steem users will get attracted to the steem blockchain which will directly lead to the onboard of new users on the steem blockchain.

#### VALUES

***A Friendly and Social Environment***

A friendly environment on the blockchain where different kind of users all over the world can co-habit and share their thoughts without any form of censorship and can also get rewarded for doing so.

***Security***

Steemblr provides a secure platform for it's users. For the steem users, you login via steemconnect and steemblr has no contact with your private keys. For the non-steem users, you also have a full guarantee of security of your keys and your account can never be tampered with by either the admin or other users.

#### Disclaimer

Steemblr is an open-source project and is subject to changes. The goals and values stated above are not compulsory obligations or duties towards any party or user and are subject to change at any moment prior to updates of the platform.

repository: snwolak/steemblr

gha_language: JavaScript

repo_name: snwolak/steemblr


text:
# HIP26: Payment Notes

- Author(s): @cvolkernick
- Start Date: 2021-01-24
- Category: Technical
- Original HIP PR: https://github.com/helium/HIP/pull/117
- Tracking Issue: https://github.com/helium/HIP/issues/125

# Summary
[summary]: #summary

This proposal suggests the addition of a new option for the Helium wallet PAY command: an optional (likely length/size restricted) alphanumeric
memo/note field included with a wallet-to-wallet HNT payment transaction.

# Motivation
[motivation]: #motivation

There have been ongoing asks within the community for some time now regarding means to contact neighboring gateway owners; evidence of this demand
can be found throughout the community discord in various channels. The ask typically centers around the coordination of gateway optimization, or other
performance issues, but also has been expressed as a means to create ties with local networks and cooperate with other hosts / owners in a way that
benefits the growth & development of the overall network. There have also been use cases stated around this such as simple notations of payments to
others, either for accounting / documentation purposes (e.g. what was the payment for) -- similar to existing payment solutions such as Venmo.

# Stakeholders
[stakeholders]: #stakeholders

* Anyone using the Helium wallet in any capacity will be affected by this change -- individuals, orgs, etc. -- whether through the wallet CLI or app UI.

Feedback and discussion on this change will be solicited & heard through the existing HIP discussion channel(s) (primarily Discord, in the respective channel),
and as usual through any git repo commentary.

# Detailed Explanation
[detailed-explanation]: #detailed-explanation

The changes as proposed should require only that an additional flag or subcommand be added, and allow a fixed-size alphanumeric text field (string) to be included
along with payment. Payment could be nothing but the network fee required to send the necessary data packet size over the network, or any normal payment figure.
This is what enables users to attach notes to payments describing what the payment was for, etc. It also consequentially enables one wallet to send messages of a
fixed length to another wallet, for a price. (Note in principle this dissuades spamming etc as you have to pay per message to send, and through UX design etc.,
messages are not required to be acknowledged or may be blocked/filtered entirely.

This could potentially also allow group broadcasts of messages as well (e.g. group messaging/announcements broadcasting, etc.) by using multipayments (payments
issued to multiple wallets in a single transaction), which is already supported.

# Drawbacks
[drawbacks]: #drawbacks

In the existing / past debates over this change, it has been argued that the ability to message hotspot owners might enable forms of harrassment and/or
present privacy concerns; however, because the contact is initiated through the owner address (which is already publicly available information), there
is no implied correlation with owner PII -- it is for all intents and purposes anonymous contact that the recipient is not obligated to acknowledge or
respond to. There are also other UX measures that could be employed to prevent harrassment / spam concerns. Address books also aid in UX ease of use,
such that they allow users to operate with saved contact data, rather than long random strings of characters which can easily be subject to copy errors,
and allow for whitelisting/blacklisting.

# Rationale and Alternatives
[alternatives]: #rationale-and-alternatives

It has been also considered, as a rule of thumb, whether this kind of service application could equally or better be served by a third party ("off-chain")
service. The key advantage that on-chain support here, is that it provides native support as each wallet on the chain is inherently in the same shared
ecosystem / community. An argument or demonstration of an equivalent ability to accomplish the same outcome off-chain is also welcome and can be presented
in the discussion phase of this proposal.

# Unresolved Questions
[unresolved]: #unresolved-questions

* Can the same goal be accomplished as effectively through other means?
* What size might payment text size be limited to & what is the added overhead to existing payment tx?
* Any other drawbacks or benefits?
* Would validators further expand the capacity to loosen text/data payload size restrictions without significant overhead?

# Deployment Impact
[deployment-impact]: #deployment-impact

Change would be deployed through a combination of an additional flag/subcommand on the existing wallet CLI pay command, and any UX changes in the Helium app
and elsewhere deemed necessary / beneficial. Documentation would need to be updated to reflect the new pay subcommand/flag and limits on size, etc. Additional data
payload / traffic would be implied. Perhaps creates an immediate use case / standin for data traffic on the network without any additional changes or equipment (sensors).

# Success Metrics
[success-metrics]: #success-metrics

Noteworthy changes would include additional overhead in terms of data sent over the network as part of these additional payment transactions. Generally feedback from
the Helium community would be solicited as to whether the new functionality was proving to be helpful and/or whether there were drawbacks in performance or user experience
that result from the new abilities. It would also be of note to monitor performance of the network (blocktimes etc) to ensure that the performance was not significantly overall.


text:
# Auth

[[toc]]

## Token

You can use this endpoint to login in the application with your account and receive a token.

- **Endpoint:**
```bash
POST https://api.proposalpage.com/accounts/auth/token
```

- **Parameters:**
    - ***Path:*** Empty.

    - ***Header:*** Empty.

    - ***Body:***

    | Name | Type | Description | Required |
    | :-: | :-: | :-: | :-: |
    | username | string | Your account username. | :heavy_check_mark: |
    | password | string | Your account password. | :heavy_check_mark: |

- **Response:**
```json
Status: 200

{
  "token": "your-token-here",
}
```

- **Example:**
```bash
curl -XPOST -H "Content-type: application/json" -d '{"username":"test@example.com","password":"test"}' 'https://api.proposalpage.com/accounts/auth/token'
```

## Me

You can use this endpoint to receive your user id.

- **Endpoint:**
```bash
GET https://api.proposalpage.com/accounts/auth/me
```

- **Response:**
```json
Status: 200

{
  "id": "your-id-here",
}
```

- **Parameters:**
    - ***Path:*** Empty.

    - ***Header:***

    | Name | Type | Description | Required |
    | :-: | :-: | :-: | :-: |
    | Authorization | string | Your Bearer Token obtained in the Auth Token endpoint. | :heavy_check_mark: |

    - ***Body:*** Empty.

- **Example:**
```bash
curl -XGET -H 'Authorization: Bearer $TOKEN' -H "Content-type: application/json" 'https://api.proposalpage.com/accounts/auth/me'
```

repository: proposal-page/api-docs

gha_language: Shell

repo_name: proposal-page/api-docs


text:
Spicetify Canvas

The first implementation of Spotify Canvas for the Desktop client ever!

## Demo

The extension is designed to show Canvases in the fullscreen view. The following are with minimal theming (this is what is included in `Themes/canvas`):

![Canvas w/o mouse overlay](https://i.imgur.com/ByZ2Yzr.png)
![Canvas, overlay](https://i.imgur.com/6hDOr7h.png)

My personal theme looks like this:

![Canvas w/ my theme](https://i.imgur.com/ysLU6mL.png)
![Canvas w/ my theme, overlay](https://i.imgur.com/KYjATiD.png)

## How it works

The mobile Spotify client uses a protocol called [Protobuf](https://developers.google.com/protocol-buffers) to communicate with the bridge/cosmos/hermes API and request a canvas link for a given track. However, the Desktop and Web clients do not have protobuf-based implementations and purely send JSON requests.

The canvas endpoint only exists in protobuf format, so you have to use some tricks to get Cosmos (the name for hermes on desktop) to give you a canvas link. Since the method only accepts string/object input, in order to send a protobuf request, I used the [JS protobuf library](https://www.npmjs.com/package/protobufjs) to first get the binary representation of my request, then I used `TextDecoder` to encode the binary into a UTF-8 string: `new TextDecoder().decode(binaryData)`. This results in a very messy not-very-UTF-8 string that is sent to the `hm://canvaz-cache/v0/canvases` endpoint. The endpoint responds with another messy string, which is then decoded into Protobuf via `new TextEncoder().encode(res._body)`.

[librespot-java](https://github.com/librespot-org/librespot-java/) was vital for figuring out the Protobuf format and endpoint for this request. Big thank you to [@devgianlu](https://github.com/devgianlu) for his work on librespot and the EntityCanvazRequest proto file.

However, UTF-8 is not a very good binary storage method and thus loses a ton of data in the process if there are any canvases present, and it's impossible to decode a full protobuf packet from the string. Luckily for us, the canvas link is 100% UTF-8 compatible and will almost always be parseable from the raw string, so I parse it out with the following regex: `/https:\/\/canvaz\.scdn\.co\/upload\/artist\/[a-zA-Z0-9]+\/video\/[a-zA-Z0-9]+.cnvs.mp4/gm`. Note that this sometimes fails (I'm assuming because of a null-byte terminator in the protobuf data response), but it's quite inconsistent.

After that, a video tag is inserted into the fullscreen overlay's DOM with the src set to the canvas.

Sounds simple, right? We're just getting started. Canvases are H.264 encoded MP4 files. Spotify's client has MP4 disabled/not supported because MP4/H.264 is a proprietary format and Spotify has no license or use for it in the desktop client. This means the video _will not play_ with all of the above I just did.

Lucky for us, Chromium Embedded Framework (the browser the client works off of) is open-source, and you can build it yourself with MP4 enabled. You can literally drag and drop replace the built pak files and DLLs into the Spotify install folder and it will just work, so long as your branch is set to the one Spotify uses.

That's it! I will elaborate on the whole CEF thing in the installation section.

## Help and Troubleshooting

This app is not very easy to install. If you come across any problems, feel free to create an issue or contact me on my [Discord](https://discord.itsmeow.dev/)

## Installation (short version)

1. Install [Spicetify](https://github.com/khanhas/spicetify-cli)
2. Run `spicetify`
3. Run `spicetify backup apply`
4. Add the extension to the Spicetify extensions folder
5. Run `spicetify config extensions getCanvas.js`
6. Add the theme to the Spicetify themes folder
7. Run `spicetify config current_theme canvas` (If you want to use your own theme, paste the user.css contents into the end of your current theme's user.css)
8. Run `spicetify apply`
9. Read and follow part two of the long installation.

## Installation (long version)

**THIS INSTALLATION IS NOT EASY. YOU WILL NEED ~50-70GB HARD DRIVE SPACE, AT LEAST 8GB RAM, GOOD COMPUTER KNOWLEDGE, A DECENT PROCESSOR, GOOD INTERNET, AND A LOT OF TIME.**

### Part One (Easy)

The first part is pretty simple. Install [Spicetify](https://github.com/khanhas/spicetify-cli), you can look at how to do that [here](https://github.com/khanhas/spicetify-cli/wiki/Installation).

After that, run the `spicetify` command with no arguments to generate your configuration.

Then run `spicetify backup apply` to patch your client.

Now, navigate to your [Spicetify extensions directory](https://github.com/khanhas/spicetify-cli/wiki/Extensions) and put `getCanvas.js` from the Extensions folder of this repository into the folder. Run `spicetify config extensions getCanvas.js` to add the extension.

Next, navigate to your [Spicetify themes directory](https://github.com/khanhas/spicetify-cli/wiki/Customization#Themes) and place the `canvas` folder from `Themes` in this repository within it. Run `spicetify config current_theme canvas` to set your theme to the new theme.

If you want to use your own theme, take the code from `Themes/canvas/user.css` and paste it at the end of your current theme. No guarantees this will work, but I tried to make it as universal and unintrusive as possible.

Next, run `spicetify apply` to load the new theme and extensions into your client.

### Part Two (Pain and Suffering)

Most extensions end installation steps here, but this extension is a LOT harder to get working due to some limitations of the Spotify client. You will need to build [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef) with proprietary codecs enabled. If you want a more detailed explanation of _why_, read "How it works".

I'd love to just post the build myself for everyone to use, but that would be violating copyright law, so you have to build it yourself.

I've only ever done this on Windows, so my instructions will be mostly catered for Windows. If someone wishes to contribute instructions for other OSes, feel free to make a pull request.

#### Pre-requisites

You will need the prerequisites for your OS listed [here](https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md) under "Platform Build Configurations". You can also view those requirements [here](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md) for more detail.

I will sum them up:

- [Python](https://www.python.org/downloads/) (2.7 or 3.8/3.9, I used 3.8)
- [Visual Studio Community 2017 or 2019, or Visual Studio Build Tools 2017 or 2019](https://visualstudio.microsoft.com/downloads/)
- "Desktop development with C++", "C++ MFC for latest v(version) build tools (x86 & x64)", C++ ATL for latest v(version) build tools (x86 & x64)" support Visual Studio components. You can install these with the "Visual Studio Installer" program, click Modify on your VS install and find those packages. You don't need the ARM components.
- "Windows 10 SDK 10.0.19041" or higher as a VS component or from [Microsoft's installer](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/). Make sure you enable the "SDK Debugging Tools" in this installer. If you use Visual Studio to install it, Chromium says you can get it from "Control Panel → Programs → Programs and Features → Select the “Windows Software Development Kit” → Change → Change → Check “Debugging Tools For Windows” → Change", but personally I had to use the installer and select _only_ the debugging tools since I already had the SDK from VS. **If you miss the debugger installation step, your build will error.**

#### Getting the branch number

Next, you need to find the CEF branch for your Spotify version. Spotify lists these relations [here](https://www.spotify.com/us/opensource/). If you hover over the "CEF version" link for your Spotify version, it links to a URL that looks like this `https://bitbucket.org/chromiumembedded/cef/get/4280.tar.bz2`. The number you want is the number before `.tar.bz2`. As of current, that branch number is `4280` in Chromium version `87.0.4280.141` for Spotify `<IP_ADDRESS>8.g7ed9c03a`.

You can verify you have the correct version by enabling devtools in spicetify `spicetify enable-devtool apply`, right clicking somewhere, press "Show Chrome Tools", and then click the `chrome://version` link. The CEF and chromium version should match.

#### Setup

Next, go to `C:\` in This PC and create a folder called `code`. Inside `code`, make a folder called `automate`, a folder called `chromium_git`, and a folder called `depot_tools`.
This is the end result:

```
C:/code/
  automate/
  chromium_git/
  depot_tools/
```

Next, download [automate-git.py](https://bitbucket.org/chromiumembedded/cef/raw/master/tools/automate/automate-git.py) and place it in `C:/code/automate/`.

Create a batch script inside `automate`, name `build.bat`. If the name change doesn't change the icon, press View in file explorer and check "File name extensions" and rename it again. Paste the following into this script and save it (you can open it by right clicking and pressing edit):

```
set CEF_USE_GN=1
set GN_DEFINES=is_official_build=true proprietary_codecs=true ffmpeg_branding=Chrome enable_nacl=false blink_symbol_level=0 symbol_level=0
set GYP_MSVS_VERSION=2019
set CEF_ARCHIVE_FORMAT=tar.bz2
python automate-git.py --download-dir=c:\code\chromium_git --depot-tools-dir=c:\code\depot_tools --branch=4280 --minimal-distrib --client-distrib --force-clean --no-debug-build
```

Change `4280` from `--branch` to the proper branch for your Spotify version.

If you use VS 2017, change `GYP_MSVS_VERSION` to 2017.

Next, open command prompt as administator (NOT POWERSHELL). You can do this by searching Command Prompt in the Start Menu, right clicking it, and pressing "Run as Administrator".

Change directories to the automate folder. `cd C:\code\automate`

#### Run it!

Execute the script. `build.bat`. This will take _many_ hours to download CEF, depot_tools, and Chromium. After which it will check out the correct branches and build Chromium.

### Possible Errors + Solutions

#### CalledProcessError: Command 'gn gen out'

If you get an error that looks like this:

```
subprocess2.CalledProcessError: Command 'gn gen out\\Debug_GN_x86 --ide=vs2019 --sln=cef --filters=//cef/*' returned non-zero exit status 1 in C:\code\chromium_git\chromium\src\...
```

It means you forgot to install the Windows SDK debugging tools. Review the Prerequisites.

#### Hash does not appear to be a valid hash in this repo

If you get an error that looks like this when it says `Running "gclient revert --nohooks"` after the download stage (I did, not sure why) `gclient_scm.NoUsableRevError: 82> Hash ee537ac096667eed6559124164c3e8482646fd77 does not appear to be a valid hash in this repo`, go to `C:/depot_tools/gclient_scm.py`, open it in a text editor, find line 879 (Ctrl + F "NoUsableRevError"), and comment out `logging.warning("Couldn't find usable revision, will retrying to update instead: %s", e.message))`. It's split onto three lines, so put a `#` before each line.

It will end up like this:

```python
    except NoUsableRevError as e:
      # If the DEPS entry's url and hash changed, try to update the origin.
      # See also http://crbug.com/520067.
      #logging.warning(
       #   "Couldn't find usable revision, will retrying to update instead: %s",
        #  e.message)
      return self.update(options, [], file_list)
```

After editing that, go to your automate batch script and add `--no-depot-tools-update` to the arguments list for the python command, otherwise your changes will be overwritten. Rerun the script, it should've saved most of the progress from that point.

### Results

After around 12 hours with my AMD Ryzen 3600, my build was completed, not counting errors and troubleshooting. The results are placed in `C:\code\chromium_git\chromium\src\out\Release_GN_x86`. You will know if it's done because `cefclient.exe` will exist in this folder. Run the client, go to some sites, make sure it works. Go to `https://html5test.com`, check under `Video` and make sure there is a check next to `H.264 support`. If not, you messed something up.

If it works, good news, you're almost done!

Now, in another Explorer, go to `%appdata%/Spotify`. You can type this in the address bar or use WinKey+R to open it. This folder contains your Spotify installation (Spotify.exe, cef.pak, etc).

The first thing you need to do is **disable auto-updating**, because Spotify will overwrite your CEF patches every time you run `spicetify apply` otherwise. Do this by deleting or renaming `SpotifyMigrator.exe` or `SpotifyUpdate.exe` if present.

Next, you will need to back up your old CEF assets. Create a folder called `backup` in the Spotify folder, and move into it all of the following files:

- cef.pak
- cef_100_percent.pak
- cef_200_percent.pak
- cef_extensions.pak
- chrome_elf.dll
- d3dcompiler_47.dll
- devtools_resources.pak
- icudtl.dat
- libcef.dll
- libEGL.dll
- libGLESv2.dll
- snapshot_blob.bin
- v8_context.snapshot.bin
- The entire `swiftshader` folder
- The entire `locales` folder

Next, from the `Release_GN_x86` folder, copy all of the files and folders with names matching the above into your Spotify folder.

The `locales` and `swiftshader` folders you copy will contain a bunch of `.info`, `.pdb`, and `.lib` files. You can delete any files that are not `.pak` or `.dll`.

You should also copy the same set of files you copied into Spotify into another, safe folder, in case Spotify updates or is uninstalled. You DO NOT want to lose them and rebuild Chromium. I also copied my entire `Release_GN_x86` folder just to be sure, but it may be large.

Finally, start Spotify! If you did things correctly, Spotify should run as normal, except now the Canvases will appear. You can delete the contents of `C:/code/chromium_git` and `C:/code/depot_tools` to save space, but I recommend keeping the script just in case Spotify updates.

If you made it this far, you are truly technically compotent! Congratulations.

#### Help and Troubleshooting

If you come accross any issues not listed above, let me know! You can create an issue here or chat in my [Discord](https://discord.itsmeow.dev/). If you find a solution to a certain issue, feel free to PR the issue and solution under the Errors header.

repository: bakzkndd/Spicetify-Canvas

repo_name: bakzkndd/Spicetify-Canvas


text:
---
title: rFacebook and redirect_to
author: Justin Ball
layout: post
permalink: /2007/10/23/rfacebook-and-redirect_to/
tags:
  - Ruby On Rails
  - redirect_to
  - rFacebook
  - ruby_on_rails
---

I have been working with rFacebook to try to get a Facebook application up and running.  Right now we are trying to integrate our conference application - 51weeks.com with Facebook so that our users can take advantage of existing social networks instead of having to create yet another network at he conference they are attending.

In working on the application I kept getting an exception related to redirect_to:

wrong number of arguments (2 for 1)

The stack trace points to this file:

controller_extensions.rb:463:in `url_for__ALIASED'

So I did what any good developer would do I went to Google and came up with this post.

The poster replaced this line in the gem:

  path = url_for__ALIASED(options, *parameters)

with this:

  path = options

I am not brave enough to mess around with the gem - it makes deployment a bit of a headache so I sat back and thought about this for a bit.  This always helps me.  I checked my facebook.yml file.  I have been using '/' as the callback_path.  I switched that to 'http://www.myserver.com/facebook/'.  Then I set the callback path inside of Facebook to 'http://www.myserver.com/facebook/'.  I made sure my canvas page url was setup correctly - 'indulgences' in my case.

Next I ran the application inside of Facebook.  Like magic everything worked.  Now even if I change my facebook.yml file back to '/' everything still seems to work.  Morale of the story is to check your configuration when building a Facebook application.  Everything has to be just right and it is easy to forget to setup any one of a number of configuration items which can cause you a lot of pain.


text:
[Back](../README.md)

## P2.1

Write a program that displays the dimensions of a letter-size (8.5 x 11 inches) sheet of paper in millimeters. There are 25.4 millimeters per inch. Use constants and comments in your program.

---

Solution:

```java
import static java.lang.System.out;

class P0201
{
  public static void main(String[] args)
  {
    final double millimetersPerInch = 25.4;
    final double paperWidthInches = 8.5;
    final double paperLengthInches = 11.0;
    final double paperWidthMillimeters = paperWidthInches * millimetersPerInch;
    final double paperLengthMillimeters = paperLengthInches * millimetersPerInch;

    out.println("The dimensions of a letter-size sheet of paper in millimeters is "
            + paperWidthMillimeters + " x " + paperLengthMillimeters + " millimeters.");
  }
}
```

repository: devtoor/bigJavaLateObjects

gha_language: Java

repo_name: devtoor/bigJavaLateObjects


text:
# Functions, loops, and `apply`
## Introduction

Most data analysis in R requires executing a particular task on multiple data observations, groups of observations, or separate data sets. Many novice users begin with the strategy of assigning a new variable for each input:

```r
x1 <- dataset1
x2 <- dataset2

meanx1 <- mean(x1)
meanx2 <- mean(x2)
```

While this certainly works, it can be very time consuming and introduces substantial risk of user error. There are several alternative strategies that can be used to repeat mathematical operations or sequences of R functions for multiple variables or data sets that avoid this risk.

The foundation for any of these strategies is a function to be repeated. Once you have a function that you would like to repeat on multiple inputs, there are a few approaches for iterating through each repetition.

In this tutorial, we will focus on the `apply` functions, which are a set of base R functions that can be used to execute a particular chunk of code on multiple inputs and generate appropriate outputs. The `apply` functions are simple to use and create very neat code, but one limitation is that they can only be used in operations for which the order of iteration is not important.

We will also introduce `for` and `while` loops, which can be used when the order of operations *does* matter.

## Writing basic functions

Functions in R take an input value, apply a process, and generate an output. R packages include numerous functions that can do nearly anything you desire, but research often requires specific processes or sequences of commands designed specifically to work with your data structure. You can write your own functions in R to perform these tasks.

Here is a very simple function:

```r
fun1 <- function (x, y){
  x + y
}
```

Here, `x` and `y` are identified as the required input variables. The code written within the brackets describes the mathematical operation to be applied to the input variables.

```r
fun1(x = 7, y = 12)
```

```
## [1] 19
```

A function can be applied to a vector of inputs. In this scenario, the function will be applied to each pair of values in the vector sequence:

```r
vals_x <- c(4, 7, 1)
vals_y <- c(2, 1, 3)

fun1(x = vals_x, y = vals_y)
```

```
## [1] 6 8 4
```
#### Nesting functions

Functions can also include other functions, which is particularly useful in the context of repeating complex data analyses. Here is a basic example:

```r
fun2 <- function (x, y){
  mean(x) + y
}

fun2(x = vals_x, y = vals_y)
```

```
## [1] 6 5 7
```

It is important to note that in this situation, the internal function (`mean()`) takes a vector of input values. This function will calculate the mean of the `vals_x` vector and then add this to each separate value of `vals_y`.

This can be very useful, but it's critical that you know exactly how your function processes input values or you may run into major problems!

#### Assigning variables within functions and `return()`

In some more complex analyses, the nested functions may generate data that needs to be stored as variables so they can be used as input for the next process. Here is a function that calculates the mean of our x values, adds y, and then generates 10 numbers from a normal distribution with a mean of the value calculated in the first step.

```r
fun3 <- function (x, y){
  val <- mean(x) + y
  dist <- rnorm(1:10, mean = val, sd = 1)
}

output <- fun3(x = vals_x, y = 3)
output
```

```
##  [1] 5.424814 6.691232 8.002993 7.730695 7.117511 7.268080 5.686973 8.485264
##  [9] 6.356877 6.405854
```

If your function assigns multiple variables, you can use `return()` to determine the data that is output from the function. This can be useful if your function includes writing a data set, or includes another process that is not intended to return anything to R as well as some process intended to return data to the R environment.

```r
dir.create('outputs')
```

```r
#Let's see what happens without using the return() function
fun4 <- function (x, y){
  val <- mean(x) + y
  dist <- rnorm(1:10, mean = x, sd = 1)
  write.csv(dist, "outputs/filename.csv")
}

output <- fun4(x = vals_x, y = 3)
output
```

```
## NULL
```

Our output here is NULL because the default output for a function will come from the last command within the function. Here, `write.csv()` does not produce data to be returned to R. If we add `return()`, our function will write the .csv and also return the data we want into the environment:

```r
#Now let's add return()
fun4 <- function (x, y){
  val <- mean(x) + y
  dist <- rnorm(1:10, mean = x, sd = 1)
  write.csv(dist, "outputs/filename.csv")
  return(dist)
}

output <- fun4(x = vals_x, y = 3)
output
```

```
##  [1] 4.3102801 7.1364540 0.4559926 4.1286090 7.9435964 2.2381301 3.1237081
##  [8] 7.0596780 2.1325763 4.1591631
```

Much better!

## Using `apply` functions

Once you have written a function, you will likely need to execute that function on multiple data sets or variables. This is where the `apply` functions come in handy.

The `apply` functions are a set of functions that can be used to, well, apply functions to lists, dataframes, and matrices. `apply` functions are similar to loops, but have a much simpler syntax.

There are several different functions that can be used depending upon the inputs and desired outputs. We will work through the following `apply` functions:

1. `apply` - used with arrays, including matrices, and returns a vector, array, or list.
2. `sapply` - (simplified apply) applies the function to each element of a vector, list, or matrix, and returns the outputs as a vector or matrix.
3. `lapply` - (list apply) is similar to `sapply`, but returns a list of objects, rather than a vector.
4. `mapply` - (multivariate apply) applies a function to the first elements of two or more vectors or lists, and then the second pair of elements, etc..

If this doesn't make much sense, don't stress! We will walk though an example of each function and situations for which they might be useful.

### `apply`

Let's generate a theoretical transition matrix for a "before" and "after" data set that shows the number of transitions from one type to another.

```r
before <- rpois(1000, lambda = 1)
after <- rpois(1000, lambda = 1)
tab <- table(before, after)
tab
```

```
##       after
## before   0   1   2   3   4   5
##      0 132 130  92  16   8   1
##      1 141 139  69  27   5   1
##      2  65  66  33   9   2   0
##      3  17  15   9   2   0   0
##      4   4  10   4   0   0   0
##      5   0   0   0   1   1   0
##      6   0   1   0   0   0   0
```

We would like to convert this table to the relative probability for each transition- that is, what is the probability that an object of type "0" in the "before" dataset transitions to a 1? To a 2? 3?

To calculate the probability, we will need to get the sum of observations in each row, and then divide each transition in that particular row by the row sum. We can do this using the `apply` function.

`apply` has three arguments: `X` is the array to which the function will be applied. `MARGIN` is used to identify whether the function should be applied to the rows, columns, or both. '1' is for rows, '2' is for columns, and c(1,2) can be used for both. `FUN` is the function to be applied.

In this scenario, we set `MARGIN = 1` so it will perform the function row wise. Up to this point, we have defined our functions outside of other commands, but in this scenario, it is a very simple function and so we can define the function within the command itself.

*Note: The `t()` function surrounding the command transposes the data set so it returns the matrix in the original orientation (before as rows and after as columns)

```r
rel_prob <- t(apply(tab, MARGIN = 1, FUN = function (i) {i/sum(i)} ))
rel_prob
```

```
##       after
## before         0         1         2          3          4           5
##      0 0.3482850 0.3430079 0.2427441 0.04221636 0.02110818 0.002638522
##      1 0.3691099 0.3638743 0.1806283 0.07068063 0.01308901 0.002617801
##      2 0.3714286 0.3771429 0.1885714 0.05142857 0.01142857 0.000000000
##      3 0.3953488 0.3488372 0.2093023 0.04651163 0.00000000 0.000000000
##      4 0.2222222 0.5555556 0.2222222 0.00000000 0.00000000 0.000000000
##      5 0.0000000 0.0000000 0.0000000 0.50000000 0.50000000 0.000000000
##      6 0.0000000 1.0000000 0.0000000 0.00000000 0.00000000 0.000000000
```

Hurray! Please not that there are other ways to perform the same task, but this one is a conceptually a simple example :)

### `sapply`

Let's check out the Loblolly dataset. It contains the height, age, and seed source of a sample of Loblolly pines.

```r
library(datasets)

data(Loblolly)
head(Loblolly)
```

```
##    height age Seed
## 1    4.51   3  301
## 15  10.89   5  301
## 29  28.72  10  301
## 43  41.74  15  301
## 57  52.70  20  301
## 71  60.92  25  301
```

The data set includes a range of ages. Let's see if we can write a function that calculates the mean height for each age group.

```r
#Create a list with each unique age group
ages <- unique(Loblolly$age)
ages
```

```
## [1]  3  5 10 15 20 25
```

```r
#Create a function that calculates the mean height for each age group
fun5 <- function (x){
  agegroup <- subset(Loblolly, age == x)
  mean_height <- mean(agegroup$height)
  return(mean_height)
}

fun5(ages)
```

```
## [1] 32.3644
```

Hmmm, this returns one value rather than a separate mean for each group. Why is that?
In this function, x is a vector, and so the subset function selects the cases where age is equal to any of the values included in the `ages` vector. Because we have selected every value of age, we will get the mean height for the entire dataset.

If we would like a vector of the means for each height, we will can use `sapply`.

```r
#Create a function that calculates the mean height for each age group
mean_heights <- sapply(X = ages, FUN = fun5)
mean_heights
```

```
## [1]  4.237857 10.205000 27.442143 40.543571 51.468571 60.289286
```

Excellent! We now have a vector with the mean height for each age group!

### `lapply`

You can use the `lapply` function to get the same information, but in a list format.

```r
heights <- lapply(X = ages, FUN = fun5)
heights
```

```
## [[1]]
## [1] 4.237857
##
## [[2]]
## [1] 10.205
##
## [[3]]
## [1] 27.44214
##
## [[4]]
## [1] 40.54357
##
## [[5]]
## [1] 51.46857
##
## [[6]]
## [1] 60.28929
```

In this scenario, `sapply` might be a better fit. `lapply` is generally more useful if your output is a an object like a `data.frame` or produces objects of different types.

Let's write a function that creates a subsetted `data.frame` for each value of tree age.

```r
ages <- unique(Loblolly$age)

func6 <- function (x){
  subset(Loblolly, age == x)
}

sub_df <- lapply(ages, func6)

#Let's look at items 1 and 2 in the list
sub_df[1:2]
```

```
## [[1]]
##    height age Seed
## 1    4.51   3  301
## 2    4.55   3  303
## 3    4.79   3  305
## 4    3.91   3  307
## 5    4.81   3  309
## 6    3.88   3  311
## 7    4.32   3  315
## 8    4.57   3  319
## 9    3.77   3  321
## 10   4.33   3  323
## 11   4.38   3  325
## 12   4.12   3  327
## 13   3.93   3  329
## 14   3.46   3  331
##
## [[2]]
##    height age Seed
## 15  10.89   5  301
## 16  10.92   5  303
## 17  11.37   5  305
## 18   9.48   5  307
## 19  11.20   5  309
## 20   9.40   5  311
## 21  10.43   5  315
## 22  10.57   5  319
## 23   9.03   5  321
## 24  10.79   5  323
## 25  10.48   5  325
## 26   9.92   5  327
## 27   9.34   5  329
## 28   9.05   5  331
```

### `mapply`

`mapply` is an extremely useful function that is a great way to avoid using `for` loops! With `mapply`, you can use multiple input variables and it will iterate through each pair (or trio or more) of variables as inputs for the function.

Let's say we would like to generate a theoretical normal distribution of tree height for each age group based on the mean and standard deviation of height. We will need a vector of means and a vector of heights to use as input values. We have already genereated a vector of means in our `sapply` example, so we will use a similar equation to generate a vector of sd.

```r
fun6 <- function (x){
  agegroup <- subset(Loblolly, age == x)
  sd(agegroup$height)
}

sd_height <- sapply(ages, fun6)
sd_height
```

```
## [1] 0.4036026 0.8155767 1.5378866 1.9508444 2.2118278 2.2688339
```

Now, we can write a function that takes the two variables and applied it to each pair of input values to generate 6 six distributions.

```r
fun7 <- function (x, y){
  rnorm(100, mean = x, sd = y)
}

height_dists <- mapply(FUN = fun7, x = mean_heights, y = sd_height)
colnames(height_dists) <- ages #This names the columns by the tree age
summary(height_dists)
```

```
##        3               5                10              15
##  Min.   :3.296   Min.   : 7.242   Min.   :24.45   Min.   :35.67
##  1st Qu.:4.032   1st Qu.: 9.521   1st Qu.:26.48   1st Qu.:38.90
##  Median :4.240   Median :10.225   Median :27.57   Median :40.37
##  Mean   :4.266   Mean   :10.211   Mean   :27.69   Mean   :40.51
##  3rd Qu.:4.493   3rd Qu.:10.906   3rd Qu.:28.73   3rd Qu.:42.23
##  Max.   :5.225   Max.   :12.192   Max.   :32.02   Max.   :44.45
##        20              25
##  Min.   :46.44   Min.   :54.12
##  1st Qu.:49.92   1st Qu.:58.51
##  Median :51.32   Median :59.89
##  Mean   :51.33   Mean   :60.12
##  3rd Qu.:52.88   3rd Qu.:61.92
##  Max.   :55.47   Max.   :64.76
```

## Loops

I haven't done this part yet!

repository: BennyWag/forest-ecology-R-book

repo_name: BennyWag/forest-ecology-R-book


text:
---
layout: page
title: external-genomes [artifact]
categories: [anvio]
comments: false
image:
  featurerelative: ../../../images/header.png
  display: true
---

{% include _toc.html %}

A TXT-type anvi'o artifact. This artifact is typically provided **by the user** for anvi'o to import into its databases, process, and/or use.

Back to the **[main page](../../)** of anvi'o programs and artifacts.

## Provided by

There are no anvi'o tools that generate this artifact, which means it is most likely provided to the anvi'o ecosystem by the user.

## Required or used by

[anvi-compute-functional-enrichment](../../programs/anvi-compute-functional-enrichment) [anvi-compute-genome-similarity](../../programs/anvi-compute-genome-similarity) [anvi-dereplicate-genomes](../../programs/anvi-dereplicate-genomes) [anvi-estimate-genome-completeness](../../programs/anvi-estimate-genome-completeness) [anvi-estimate-metabolism](../../programs/anvi-estimate-metabolism) [anvi-gen-genomes-storage](../../programs/anvi-gen-genomes-storage) [anvi-get-sequences-for-hmm-hits](../../programs/anvi-get-sequences-for-hmm-hits) [anvi-script-gen-hmm-hits-matrix-across-genomes](../../programs/anvi-script-gen-hmm-hits-matrix-across-genomes)

## Description

An external genome is any genome assembly that was converted into a [contigs-db](/software/anvio/help/7/artifacts/contigs-db) from its original FASTA file format using the program [anvi-gen-contigs-database](/software/anvio/help/7/programs/anvi-gen-contigs-database). You can obtain one of these in a variety of ways, the most common being 1) downloading a genome from a database such as NCBI and 2) assembling a genome yourself from sequencing reads. The key thing is that the sequences in the [contigs-db](/software/anvio/help/7/artifacts/contigs-db) represent a _single_ microbial population (or species, if you are not working with microbes) - ie, it is not a metagenome.

The external genomes file format enables anvi'o to work with one or more external genomes. A TAB-delimited external genomes file will be composed of at least the following two columns:

|name|contigs_db_path|
|:--|:--|
|Name_01|/path/to/contigs-01.db|
|Name_02|/path/to/contigs-02.db|
|Name_03|/path/to/contigs-03.db|
|(...)|(...)|

{:.warning}
Please make sure names in the `name` column does not include any special characters (underscore is fine). It is also a good idea to keep these names short and descriptive as they will appear in various figures in downstream analyses.

## Additional columns

In some cases additional columns may be required to be in this file. Below is a table of the possible columns you may need.

| header | description | required for |
|----|----|----|
| group | which group the genome belongs to (can be empty) | [anvi-compute-functional-enrichment](/software/anvio/help/7/programs/anvi-compute-functional-enrichment) |

Also see **[internal-genomes](/software/anvio/help/7/artifacts/internal-genomes)** and **[metagenomes](/software/anvio/help/7/artifacts/metagenomes)**.

{:.notice}
Edit [this file](https://github.com/merenlab/anvio/tree/master/anvio/docs/artifacts/external-genomes.md) to update this information.

repository: genomewalker/web

repo_name: genomewalker/web


text:
## SINF Project

Project of SINF (Informations Systems - 4rd year of Integrated Master Degree in Computer Engineering).
The goal of the project was to use the Primavera's ERP and integrate it with a Web App for warehouse management.
The app allows the user to manage all the logistics activity of a company, including generating delivery notes,
goods receipt, manage inventory and handle replenishment and allocation to warehouse with the calculation of an optimal
picking route.

### Course Information

* All the course's information can be viewed [here](https://sigarra.up.pt/feup/en/ucurr_geral.ficha_uc_view?pv_ocorrencia_id=459494).

### Authors

* **Ana Loureiro** - [anamargaridarl](https://github.com/anamargaridarl)
* **Carlos Albuquerque** - [CajoAlbuquerque](https://github.com/CajoAlbuquerque)
* **João Martins** - [joaomrcsmartins](https://github.com/joaomrcsmartins)
* **Tito Griné** - [TitoGrine](https://github.com/TitoGrine)

### Evaluation

**Project Grade:** 17.68


text:
---
layout: post
title:  "Spicy dry fried beef with roast tomato salsa taco-a-likes"
date:   2019-03-17 15:35:00
publishdate:   2019-03-17 15:35:00
author: oli
tags: ["beef", "tacos", "hummus","2019"]
image: "/images/blog/dry-beef-roast-salsa-tacos-a-likes.jpg"
---

Another using up meal which turned out really well.  I firmly believe that food you put togehter with your hands at the table is always the most fun, this being no exception.

You could make endless substitutions here, swaps the types of beans, the meat, the cheese, I suspect so long as you've a combination of meat, spice, bread will work ok.

I can't really claim they're tacos, but I don't have better words for the combo.

## You will need

### The bread

* About 150g of plain flour between two
* Enough cold water to bind into a smooth dough
* A couple of teaspoons of olive oil
* A good pinch of salt

### The hummus

* A tin of canned beans - I used butter beans but chickpeas, kidney beans, black eye beans have all worked
* A couple of heaped teaspoons of tahini
* A lug of olive oil
* A good squeeze of lemon juice
* A pinch of rock salt

### The beef

* 200g of quality miced beef
* A heaped teaspoon of ras el hanout
* A teaspoon of black pepper corns coursed ground

### The cheese

* A block of halloumi, cut into slices a little less than 1cm thick

### The roast salsa

* A handful of good tomatos
* A handful of sweetcorn
* A green herb (I used parsley)
* A couple of teaspoons of hot sauce (I used a California Reaper based one)

## Do

The aim here is to get everything to be ready at the same time, which isn't easy unless you've got help. The bonus is that everything except the breads and the cheese will wait whilst you cook the other bits.

### The salsa (10 minutes)

* Pop the tomatos under a hot grill
* Once they'er nearly blackened on the outside add the corn
* Once everything is a little black, mash it all and stir though the hot sauce
* Chop the green herb and stir though once the salsa has cooled a bit
* Set aside until you're ready to eat

### The hummous (2 minutes)

* Drain the deals
* Mash the beans, tahini, lemon juice and a few teaspoons of olive oil until smooth
* Stir though the rock salt

### The beef (10 minutes)

* Get a frying pan reasonably hot
* Add a teaspoon of sunflower oil and the mince
* Keep it all moving until the beef is nearly browned
* Stir thought ras el hanout and black pepper
* Keep it moving so the spices down burn
* Set aside until you're ready to eat (don't panic that it looks dry)

### the cheese (5 minutes)

* Get a frying pan reasonably hot
* Add a teaspoon of sunflower oil
* Fry the halloumi until golden on both sides (a couple of minutes)

### The bread (10 minutes)

* Mix and kneed flour, oul and enough water to make a smooth dough
* Divide it into about 8 balls
* Roll out to a few millimeters thick
* Drop them into a hot dry frying pan and turn once they start to blister

## Result

Fun to assemble.    Finger fold to eat.

Sorry, only one photo, I was too busy eating.

![Get in my face](/images/blog/dry-beef-roast-salsa-tacos-a-likes.jpg)

repository: coldclimate/omnomfrickinnom

extension: markdown

repo_name: coldclimate/omnomfrickinnom


text:
### New in 0.0.4 (Released 2014/10/14)
* clone messages improved to match up with Git behaviour
* clone no longer displays checkout file paths
* `IObservableRepository.Inner` is available for when you need to access the
 underlying LibGit2Sharp repository

### New in 0.0.3 (Released 2014/10/12)
* a proper build process, just like a real OSS project
* now targets LibGit2Sharp v0.19

**Breaking changes:**
 - The `Credentials` `ctor` have been deprecated upstream in favour of
 `CredentialsHandler` delegates.

repository: shiftkey/ReactiveGit

repo_name: shiftkey/ReactiveGit


text:
# QUINE-ES

It is strongly recommended that users interested in this repository read the wiki available, along with release notes.

This program is intended for security purposes, and has functions for learning, decision making and inference based on expert system ruling, but does not come with a knowledge base.

The reason for not including a knowledge base is listed on the home page of the wiki.

If you are unfamiliar with how to use and implement prolog scripts, it is strongly encouraged that you review the available documentation on the official swi-prolog site, which is linked on the home page of the wiki.

repository: functionals/QUINE-ES

repo_name: functionals/QUINE-ES


text:
Terraform provisioner example
=============================

This example is very basic and assumes that you already have an EKS cluster on
AWS. See comments in [`main.tf`] for further explainations.

Copy tfvars file and adjust to your needs:

```sh
$ cp config.auto.tfvars.example config.auto.tfvars
```

Initialize terraform:

```sh
$ terraform init
```

Run `kcm provision` in dry-run mode to see what happens.

```sh
$ kcm provision --config config.yaml --dry-run
```

kcm will retrieve the `kubeconfig` and `context` from the terraform output.
Check [`main.tf`](main.tf) for an example how to pass these values from
terraform to kcm. You can also provide the kubernetes credentials to kcm via
the `--cluster-*` command line flags.

repository: martinohmann/kubernetes-cluster-manager

gha_language: Go

repo_name: martinohmann/kubernetes-cluster-manager


text:
---
added: 2017-09-01 17:09:00+00:00
creators:
- email<EMAIL_ADDRESS>  name: Ed Summers
dates:
- end: '2017-08-23'
  start: '2017-08-17'
published: 2017-09-01
repository: Internet Archive
subjects:
- Astronomy
- Eclipse
title: 2017 Eclipse
tweets: 13548321
url: https://archive.org/details/eclipse-tweets.csv
---

The 2017 solar eclipse occurred on August 21 and and was total for Oregon, Idaho, Wyoming, Nebraska, Kansas, Missouri, Illinois, Kentucky, Tennessee, North Carolina, Georgia, and South Carolina.  This dataset includes 13,548,321 tweet identifiers for tweets that included any of the keywords solareclipse2017, solareclipse, eclipse2017, eclipseday or eclipse for the period August 17 to August 23, 2017.  The hashtags were were selected after watching Twitter's streaming API for the trending hashtag #solareclipse2017 and counting the most popular co-occurring hashtags. The search API was used instead of the filter stream API because the stream was emitting notifications that many tweets were not delivered, since the volume was so high.

repository: remagio/catalog

repo_name: remagio/catalog


text:
# gluon-language-server

This implements the [language server protocol](https://microsoft.github.io/language-server-protocol/) and offers gluon support for the LSP clients, like [VSCode](https://code.visualstudio.com/), [Atom](https://atom.io/) and many others.

## vscode-gluon

Also part of this repo is the extension for [Visual Studio Code][] which is based on the LSP implementation.

## Installing the language server

The language server is available at [crates.io][] and can be installed by running `cargo install gluon_language-server`. After installing the extension you will need to either make the language server executable available in `$PATH` or set the `gluon.language-server.path` option to exectuables path.

```json
{
    "gluon.language-server.path": "gluon_language-server",

    // Gluon specific settings can be specified with
    "[gluon]": {
        "editor.formatOnSave": false
    }
}
```

## Features

* Code completion

* Hover support

* Symbol highlighting

* Symbol lookup

* Code formatting (May still eat your laundry)

## Example

![example](https://i.imgur.com/44bH0ww.gif)

[Visual Studio Code]:https://code.visualstudio.com/
[gluon]:https://github.com/gluon-lang/gluon
[crates.io]:https://crates.io/

gha_language: Rust


text:
**PROJECT TITLE**

**GOAL**

Write the main goal of this project and what's the purpose of it

**PURPOSE**

What's the purpose of this issue and the outcome you expected

**DATASET**

Add a link to dataset and from where it's taken.

**DESCRIPTION**

Short description about the idea and approach you had gone with

**WHAT I HAD DONE**

Write down the step by step procedure of how your project file works using points.

**WORKFLOW OF YOUR PROJECT FILES**

Add the workflow of the script point by point to get good understanding of the program

**STATE YOUR PROCEDURE AND UNDERSTANDING FROM YOUR WORK**

List out the procedure you had used and how did you implement it.

Why had you choose this approach and what is your understanding from your work you had done.

What did you learn while working on this issue.

Why have you choosed this methodology should also be stated

**DETAILED EXPLANATION OF SCRIPT, IF APPLICABLE**

Provide detailed explanation of the script in elaborative manner using points

**LIBRARIES NEEDED**

Add all the libraries that had been imported in this project in points.

**COMPILATION STEPS**

Briefly show the compilation steps of the issue you had worked on

**RESEARCH**

Have you done any research for this PR, if so describe more on it

**SCREENSHOTS**

Add screenshots of the output or anything related to your script to show it works

**CONCLUSION**

What's the conclusion derived from this project and also showcase the appropriate results gained if it's applicable. Be briefer.

**REFERENCES**

Add all the references you had gone through to make your PR successful.

**NAME OF AUTHOR**

Add your name at the end of the file, along with social media handles if applicable.

**DISCLAIMER, IF ANY**

Use this section to mention if any particular disclaimer is required


text:
# PrySyslog

This Pry plugin was originally written to solve an auditing issue in production
instances. Using auditd we're able to log all commands executed, but that only
extends to the application that was executed (which for pry is ruby). Relying
exclusively on .pry_history files for auditing wasn't sufficient.

This gem will log all valid Ruby executed in a pry session to syslog at the
'info' message level on the 'local1' logging facility. Additionally the custom
app name of 'pry_history' will be used. This isn't currently configurable.

This plugin is non-invasive to anything pry related as it makes use of Pry's
native exposed hooks.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'pry-syslog'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install pry-syslog

## Usage

When this gem is installed anytime Pry gets executed from any context it will
automatically detect and load this plugin. When this happens you will see a
note like the following indicating the session is being logged:

```
[user@host ~/] $ pry
Please note: This interactive session has PrySyslog enabled. All
valid Ruby entered here will be sent to Syslog before being executed
for auditing purposes.
[1] pry(main)>
```

## Contributing

I welcome new ideas, bug fixes and comments from anyone and strive to take no
longer than a week to respond to issues, PRs, or various comments.

All code submitted through PRs will be licensed under this project's MIT
license, if this is a problem please instead open an issue before making your
changes indicating this and I depending on the request I may make the requested
changes myself or attempt to convince about the usage of this license. I want
to avoid a multi-license code base that may impede any individual's usage of
this code.

With all that said, if you'd like to contribute please follow the standard
contribution guide:

1. Review the [Contributor Code of Conduct][1]
2. Fork it ( https://github.com/sstelfox/pry-syslog/fork )
3. Create your feature branch (`git checkout -b my-new-feature`)
4.  Push to the branch (`git push origin my-new-feature`)
6. Create a new Pull Request against this repo's develop branch

[1]: CODE_OF_CONDUCT.md

repository: sstelfox/pry-syslog

repo_name: sstelfox/pry-syslog