text:
<?php

namespace Oro\Bundle\ImapBundle\Tests\Unit\Entity;

use Oro\Bundle\ImapBundle\Entity\ImapEmailOrigin;

class ImapEmailOriginTest extends \PHPUnit_Framework_TestCase
{
    const TEST_STRING    = 'testString';
    const TEST_ID        = 123;
    const TEST_FLOAT     = 123.123;

    /** @var ImapEmailOrigin */
    protected $entity;

    public function setUp()
    {
        $this->entity = new ImapEmailOrigin();
    }

    /**
     * @dataProvider  getSetDataProvider
     *
     * @param string $property
     * @param mixed  $value
     * @param mixed  $expected
     */
    public function testSetGet($property, $value = null, $expected = null)
    {
        if ($value !== null) {
            call_user_func_array(array($this->entity, 'set' . ucfirst($property)), array($value));
        }

        $this->assertEquals($expected, call_user_func_array(array($this->entity, 'get' . ucfirst($property)), array()));
    }

    /**
     * @return array
     */
    public function getSetDataProvider()
    {
        return [
            'host'        => ['host', self::TEST_STRING, self::TEST_STRING],
            'port'        => ['port', self::TEST_ID, self::TEST_ID],
            'ssl'         => ['ssl', self::TEST_STRING, self::TEST_STRING],
            'user'        => ['user', self::TEST_STRING, self::TEST_STRING],
            'password'    => ['password', self::TEST_STRING, self::TEST_STRING],
        ];
    }
}


text:
package cromwell

import akka.testkit._
import wdl4s.types.{WdlMapType, WdlStringType, WdlArrayType}
import wdl4s.values.{WdlMap, WdlArray, WdlString}
import cromwell.CromwellSpec.DockerTest
import cromwell.util.SampleWdl

import scala.language.postfixOps

class WdlFunctionsAtWorkflowLevelSpec extends CromwellTestkitSpec {
  val outputMap = WdlMap(WdlMapType(WdlStringType, WdlStringType), Map(
    WdlString("k1") -> WdlString("v1"),
    WdlString("k2") -> WdlString("v2"),
    WdlString("k3") -> WdlString("v3")
  ))

  "A workflow with a read_lines() and read_map() at the workflow level" should {
    "execute those functions properly" in {
      runWdlAndAssertOutputs(
        sampleWdl = SampleWdl.WdlFunctionsAtWorkflowLevel,
        eventFilter = EventFilter.info(pattern = s"starting calls: w.a", occurrences = 1),
        expectedOutputs = Map(
          "w.a.x" -> WdlString("one two three four five"),
          "w.a.y" -> outputMap
        )
      )
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.android.quizapp.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/image_quiz_app_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:contentDescription="@string/quiz_app_title_content_description"
            android:scaleType="centerCrop"
            android:src="@drawable/quiz_app_title" />

        <LinearLayout
            android:id="@+id/layout_questions"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/image_quiz_app_title"
            android:layout_marginEnd="@dimen/activity_vertical_margin"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:layout_marginRight="@dimen/activity_horizontal_margin"
            android:layout_marginStart="@dimen/activity_vertical_margin"
            android:orientation="vertical">

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_1" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_1" />

            <RadioGroup
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <RadioButton
                    android:id="@+id/radio_question_1_option1"
                    style="@style/QuestionOption"
                    android:text="@string/question_1_option_1" />

                <RadioButton
                    android:id="@+id/radio_question_1_option2"
                    style="@style/QuestionOption"
                    android:text="@string/question_1_option_2" />

                <RadioButton
                    android:id="@+id/radio_question_1_option3"
                    style="@style/QuestionOption"
                    android:text="@string/question_1_option_3" />
            </RadioGroup>

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_2" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_2" />

            <RadioGroup
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <RadioButton
                    android:id="@+id/radio_question_2_option1"
                    style="@style/QuestionOption"
                    android:text="@string/question_2_option_1" />

                <RadioButton
                    android:id="@+id/radio_question_2_option2"
                    style="@style/QuestionOption"
                    android:text="@string/question_2_option_2" />

                <RadioButton
                    android:id="@+id/radio_question_2_option3"
                    style="@style/QuestionOption"
                    android:text="@string/question_2_option_3" />
            </RadioGroup>

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_3" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_3" />

            <RadioGroup
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <RadioButton
                    android:id="@+id/radio_question_3_option1"
                    style="@style/QuestionOption"
                    android:text="@string/question_3_option_1" />

                <RadioButton
                    android:id="@+id/radio_question_3_option2"
                    style="@style/QuestionOption"
                    android:text="@string/question_3_option_2" />

                <RadioButton
                    android:id="@+id/radio_question_3_option3"
                    style="@style/QuestionOption"
                    android:text="@string/question_3_option_3" />
            </RadioGroup>

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_4" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_4" />

            <CheckBox
                android:id="@+id/check_question_4_option1"
                style="@style/QuestionOption"
                android:text="@string/question_4_option_1" />

            <CheckBox
                android:id="@+id/check_question_4_option2"
                style="@style/QuestionOption"
                android:text="@string/question_4_option_2" />

            <CheckBox
                android:id="@+id/check_question_4_option3"
                style="@style/QuestionOption"
                android:text="@string/question_4_option_3" />

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_5" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_5" />

            <CheckBox
                android:id="@+id/check_question_5_option1"
                style="@style/QuestionOption"
                android:text="@string/question_5_option_1" />

            <CheckBox
                android:id="@+id/check_question_5_option2"
                style="@style/QuestionOption"
                android:text="@string/question_5_option_2" />

            <CheckBox
                android:id="@+id/check_question_5_option3"
                style="@style/QuestionOption"
                android:text="@string/question_5_option_3" />

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_6" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_6" />

            <CheckBox
                android:id="@+id/check_question_6_option1"
                style="@style/QuestionOption"
                android:text="@string/question_6_option_1" />

            <CheckBox
                android:id="@+id/check_question_6_option2"
                style="@style/QuestionOption"
                android:text="@string/question_6_option_2" />

            <CheckBox
                android:id="@+id/check_question_6_option3"
                style="@style/QuestionOption"
                android:text="@string/question_6_option_3" />

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_7" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_7" />

            <EditText
                android:id="@+id/text_question_7"
                style="@style/QuestionTextField" />

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_8" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_8" />

            <EditText
                android:id="@+id/text_question_8"
                style="@style/QuestionTextField" />

            <View style="@style/ViewSeparator" />

            <TextView
                style="@style/QuestionHeader"
                android:text="@string/question_9" />

            <TextView
                style="@style/QuestionText"
                android:text="@string/question_text_9" />

            <EditText
                android:id="@+id/text_question_9"
                style="@style/QuestionTextField" />

            <View style="@style/ViewSeparator" />
        </LinearLayout>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/layout_questions"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="16dp"
            android:onClick="checkAnswer"
            android:text="@string/btn_check_answer" />
    </RelativeLayout>
</ScrollView>


text:
package de.kumpelblase2.remoteentities.api.selectors;

import net.minecraft.server.v1_7_R1.*;

public class EntitySelectorMonster implements IEntitySelector
{
	@Override
	public boolean a(Entity inEntity)
	{
		return inEntity instanceof IMonster;
	}
}


text:
Español

Hello!

Another article in the particles series! The first one presented all the results, so now I want to talk about different parts of the final product. In this case I want to talk about the colorization, or how the particles end up being red, white, blue or some other mix of those.

Red, White and Density

Like I said in the first entry, I wanted to show the properties of each type of random position generation using a density visualization, in essence that means that the color is an indicator of how populated is the space around each particle: redder particles have less neighbors, white particles have more. The detail is "less" and "more" are defined relatively to the maximum value in the entire amount of particles. The value of density then is very simple (conceptually) to calculate but a little costly.

Calculating Density

The most basic version of the density calculation is as simple as:
[code language="cpp"]
void update_density(std::vector<Particle>& particles) {
    for (auto& p1 : particles) {
        for (auto& p2 : particles) {
            if (p1.dist2(p2) < THRESHOLD_DIST) {
                p1.density++;
            }
        }
    }
}
[/code]
The two most important things to notice here are,

There is a lot of wasted computing repeating operations.

This function order of execution is O(N^2) with N being the number of particles

Don't repeat work

The first approach to improving this 2 problems is very simple and involves avoid doing the same calculation twice. On each loop the same particle will take the place of p1 and then p2 so we'll eventually do p1.dist2(p2) & then p2.dist2(p1). Let's avoid this:
[code language="cpp"]
void update_density(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        auto& p1 = particles[ix];
        for (auto jx = ix + 1; jx < particles.size(); jx++) {
            auto& p2 = particles[jx];
            if (p1.dist2(p2) < THRESHOLD_DIST) {
                p1.density++;
                p2.density++;
            }
        }
    }
}
[/code]
With this small change, we avoid doing lots of calculations twice, because each iteration updates the density of both particles (and we prevent from calculating again both values by only comparing each particles with the following ones).

The order of execution did not changed that much though, we now do comparisons in this series:

The order still is quadratic. We need a way to drastically reduce the amount of calculations we do.

Locality of the problem

We're trying to visualize the particle density value at each particle which means we need a threshold value small enough to have some sense in the final image. Since we're plotting particles in the surface of the unit sphere (1 unit radius), the maximum distance between 2 particles is 2 units (diameter). I picked sqrt(0.004) ~ 0.063 (the tests are done with all distances squared so that we don't need to use the square root) as my threshold value, it could've been any number but this one resulted we from the beginning.

If you compare both values you know that many, MANY particles are far away from each other, we can use a data structure suitable to just discard as many comparisons as possible before even doing them. Structures for this kind of range based distance calculations are within the family of the spatial tree structures like quadtrees, octrees, BSP trees and kd-trees to name a few.
In fact, in ray tracing using the Photon Mapping technique, it's very common to use kd-trees as the Photon Map base for the quality of the distance range queries to retrieve photons closer to a given position in space.

The only caveat it's that it might get costly to maintain a kd-tree if the points are dynamically created an removed (the tree will eventually have to be re balanced many times), since I wanted to eventually animate the particles, that was an inconvenience.

What I ended up implementing is a hacky-dirty version of a fixed size leaf octree (anyone can argue that this code could be licensed under CRAPL instead of MIT, but hey, it worked fine and was easy ;P). Instead of dynamically creating a tree structure, I defined 2 parameters, a bounding box for the model (given by the maximum and minimum values any coordinate can take) and a number of intervals each axis will be subdivided.

The base structure is a hashmap of vectors (sets might've worked too, even better...) where each key is the indentifier generated based on a position and the value is a vector of all the elements that are within one leaf of this thing.

Now, instead of comparing with all the particles, a great portion of them is discarded with little trouble and only the best candidates are used in the comparison.

SPP or "Space Partitioned Positions"

This is the accelerator structure I've used:
[code language="cpp"]
class spp {
public:
    spp(uint8_t intervals_per_axis, float min_val, float max_val);
    ~spp() = default;

    uint32_t add(const glm::vec3& pos, size_t external_idx);
    void remove(const glm::vec3& pos, size_t external_idx);
    void remove(uint32_t bucket_id, size_t external_idx);
    std::vector<uint32_t> get_buckets_area(const glm::vec3& pos) const;
    std::vector<uint32_t> get_buckets_area(uint32_t bucket_id) const;
    const std::vector<size_t>& get_bucket(uint32_t bucket_id) const;
private:
    std::unordered_map<uint32_t, std::vector<size_t>> m_buckets;
    uint8_t m_intervals_per_axis;
    glm::vec3 m_min_vec;
    float m_normalize_value;

    uint32_t get_bucket(const glm::vec3& pos) const;
};
[/code]
Step by step:
[code language="cpp"]
spp::spp(const uint8_t intervals_per_axis, const float min_val, const float max_val)
    : m_intervals_per_axis(intervals_per_axis)
    , m_min_vec{ min_val, min_val, min_val }
    , m_normalize_value(max_val - min_val) {
    SPL_ASSERT(m_normalize_value != 0., "SPP interval can't be zero.");
    SPL_ASSERT(max_val > min_val, "Consider swapping min and max!");
}
[/code]
This is the constructor, initializes the auxiliary members and makes some simple controls. The members are a vector (to simplify sintax, it could've been just the value) for the minimum value, another for the interval count (with a maximum number of intervals equal to 0xFF or 255) and a third one for the length of the bounding box (per axis). (By how it works, using either 0 or 1 as the number of intervals will have the same effect).
[code language="cpp"]
uint32_t spp::add(const glm::vec3& pos, const size_t external_idx) {
    const auto bid = get_bucket(pos);
    m_buckets[bid].push_back(external_idx);
    return bid;
}
[/code]
This method adds an element to the structure, the element is referenced with the external_idx (in my case I was using indices to reference each particle outside) and the pos variable is the position of the element.

As you can see, it generates the key associated with the storage bucket using the position, stores the id in the bucket and finally returns the bucket identifier. Since calculating the id from the position is a costly operation, in the rest of the code I optimized a bit the usage of the structure by storing the id of the bucket each particle belongs to. This is not necessary since the position alone is enough to map a particle to a bucket.
[code language="cpp"]
void spp::remove(const glm::vec3& pos, const size_t external_idx) {
    remove(get_bucket(pos), external_idx);
}
void spp::remove(const uint32_t bucket_id, const size_t external_idx) {
    auto& b = m_buckets[bucket_id];
    b.erase(std::find(b.begin(), b.end(), external_idx));
}
[/code]
Now we have the remove methods, one overload using the position and the other using directly the bucket id, this is the operation that could be used to argue in favor of using a hashmap of sets instead of one of vectors, but I didn't do any performance comparison to make the change (others parts of the code might work worse in a set than in a vector, because of cache misses and data locality).

Now let's jump to the interesting method, get_bucket:
[code language="cpp"]
uint32_t spp::get_bucket(const glm::vec3& pos) const {
    const auto norm = (pos - m_min_vec) / m_normalize_value;
    return pack(
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.x)),
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.y)),
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.z)));
}
[/code]
You can see here what's being done, each coordinate is mapped to the [0, 1] interval using the constructor parameters and then that value is used to obtain a uint8_t value based on the number of intervals. Finally the 3 values are packed on a single uint32_t value using the pack method.

How does this works? Let's think about it in a single dimension:

Using 8 as the number of intervals (intervals_per_axis), suppose we get pos = -0.3:

So our bucket id is number 2.
Doing the same for 0.5 we get: bucket id = 6. And finally, using a value very close to 0.5 we should get either the same bucket or the contiguous ones, for 0.55 -> 6, for 0.45 -> 5, for 0.75 -> 7. We are effectively dividing the interval in smaller ones with the lenght equal to the size of the bounding box (per axis) divided by the number of intervals and assigning the ids based on within which interval the position falls.

If you've ever read about scalar quantization or float packing (like color channels into a single integer) this is the same.

The general result is:

It is certain that the maximum distance within elements on the same bucket is equal to:

Unfortunately that doesn't mean a single bucket is enough to calculate the density around each particle, since 2 very close particles could end up in neighboring buckets but...

We can obtain all the particles that are within X value by using the bucket the particle falls and all the neighboring ones provided that X is smaller than m_normalize_value/m_intervals_per_axis.

In our one dimensional case, the maximum distance between 2 values in the same bucket is 0.25, and taking any position P within bucket B, we can calculate all the positions with a distance smaller than 0.25 to P by analyzing only the particles in buckets B, B - 1 (if B != 0) and B + 1 (if B != 7). So by dividing our original set in 8, we've reduced the number of positions we need to test to those only in 3 of the 8 buckets (in the worst case).

Moving on:
[code language="cpp"]
std::vector<uint32_t> spp::get_buckets_area(const uint32_t bucket_id) const {
    std::vector<uint32_t> buckets;
    buckets.reserve(3 * 3 * 3); // Max adjacent buckets (think of a rubik's cube)
    const auto unpacked = unpack(bucket_id);
    for (int8_t ix = -1; ix < 2; ix++) {
        const int8_t xval = unpacked[0] + ix;
        if (xval >= 0 && xval < m_intervals_per_axis) {
            for (int8_t iy = -1; iy < 2; iy++) {
                const int8_t yval = unpacked[1] + iy;
                if (yval >= 0 && yval < m_intervals_per_axis) {
                    for (int8_t iz = -1; iz < 2; iz++) {
                        const int8_t zval = unpacked[2] + iz;
                        if (zval >= 0 && zval < m_intervals_per_axis) {
                            const auto potential_id = pack(xval, yval, zval);
                            if (m_buckets.find(potential_id) != m_buckets.end()) {
                                buckets.push_back(potential_id);
                            }
                        }
                    }
                }
            }
        }
    }
    return buckets;
}
[/code]
This code allows us detect this set of bucket+neighbors by calculating the valid values for each part of the packed id (imagine a rubik's cube center, and the positions of all the other pieces). Given a single bucket id we get that one and the 26 neighboring ones (at worst). Finally, pack and unpack are methods to pack 3 (they could be 4) 8 bit integers into a single 32 bit one.
[code language="cpp"]
static uint32_t pack(const uint8_t x, const uint8_t y, const uint8_t z) {
    return  x << 16 | y << 8 | z;
}
static std::array<uint8_t, 3> unpack(uint32_t value) {
    return{
        (value >> 16) & 0xFF,
        (value >> 8) & 0xFF,
        value & 0xFF
    };
}
[/code]

Using the SPP

Now that we have our SPP structure up and running, instead of computing the density by calculating the distance to all particles, we:

Add all particles to the SPP and then,

For each particle updated we obtain the set of buckets neighboring it and,

Calculate the distance to all particles within those buckets and those only:

[code language="cpp"]
void load_particles(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        // Note we store the bucket id outside to reduce the amount of times we need to calculate it later.
        p.bucket_id = spp.add(p.position, ix);
    }
}

void update_density(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        auto& p1 = particles[ix];
        auto buckets = spp.get_buckets_area(p1.bucket_id);
        for (auto jx = 0u; jx < buckets.size(); jx++) {
            auto& bucket = spp.get_bucket(buckets[jx]);
            for (auto kx = 0u; kx < bucket.size(); kx++) {
                auto& p2 = particles[bucket[kx]];
                if (p1.dist2(p2) < THRESHOLD_DIST) {
                    p1.density++;
                }
            }
        }
    }
}
[/code]
Note that now, I'm again repeating a bit of work, since I'm not updating both density values in the same loop, the thing is I can no longer ensure how the particles will be iterated, so trying to avoid counting twice gets more complicated. The savings of using the spp are more than enough to compensate for this (and the possible complexity of an algorithm that would correctly skip already made comparisons).

After this, calculating the color for each particle it's just a matter of finding the maximum density and getting an RGBA value based on the density of each particle in comparison with the maximum one. I've used someting along this lines:
[code language="cpp"]
Color color_for_particle(Particle& p, const uint32_t max_density) {
    float alive_value = p.isAlive() ? 1.f : 0.f; //Just cast it if you like :)
    return Color {
        alive_value,
        (p.density / max_density) * alive_value,
        (p.density / max_density) * alive_value,
        alive_value
    };
}
[/code]
You can see in the history of the repo, that at first this calculation was performed on CPU and then forwarding the color directly on the shader. Obviously this is not the best thing, in the current version, only the maximum value is calculated in CPU then passed as a uniform, and the density por particle is passed as another attribute. That way, the calculation can be performed on the GPU.

Blue, Red and distance to center

In this demo, the calculations are much simpler, nothing is done on the CPU and the shader outputs Red if the particle distance to the center is less than 1 and Blue otherwise.
[code language="cpp"]
Color color_for_particle_blue(Particle& p) {
    float alive_value = p.isAlive() ? 1.f : 0.f; //Just cast it if you like :)
    float r = (p.length <= 1.) ? 1.f : 0.f; //Just cast it if you like :)
    return Color {
        r,
        0.f,
        1.f - r,
        alive_value
    };
}
[/code]

Footnote on the SPP number of intervals

The number of buckets directly influences the amount of comparisons we need to perform but also the maximum distance 2 particles can have. We need to instantiate the SPP with the correct value so to skip as many particles as possible and to avoid missing particles that should be part of the density. To calculate it we need to 'enclose' the volume of closeness around the particle in the cube created by the bucket the particle belongs and all the neighbors:

Having chosen a density threshold equal to srqr(0.004) ~ 0.0632 we need an bucket size (per axis) that is at least this big.

We know the maximum value a coordinate can have is 1, and the minimum is -1, so our bbox is 2 units wide on each axis

This number of intervals per axis, give us a bucket size (per axis) of ~0.645 units, the smallest value not smaller than our threshold. This ensures that even the worst case scenario is covered, and all particles that will contribute to the density of a given particle are tested.

The worst case scenario is given by a particle laying on any of the bordering planes of the bucket. Thinking again in our 1 dimensional sample, if our threshold is 0.26, having 8 intervals is too much: a sample with the position 0.5 will be in bucket 6, and a sample with position 0.245 will end up in bucket 4. Those 2 won't be compared since are not in neighboring buckets even if the distance between them is less than 0.26.

OK! The end! You've made it through a long article about details of an unimportant demo, congrats! At least I hope you get something useful out of it. You can refer to the previous article for the original story and the source code.
Back to Top

¡Buenas!

¡Otro artículo en la serie de las partículas! En el primero presenté los resultados, así que ahora quiero hablar de las diferentes partes del producto final. En este caso, sobre cómo colorear las partículas para que terminen siendo rojas, blancas, azules o alguna combinación.

Rojo, Blanco y la Densidad

Como comenté en la primera entrada, quería mostrar las propiedades de cada función para generar posiciones aleatorias usando una visualización de densidad, en esencia significa que el color es un indicador de qué tan poblado es el espacio alrededor de cada partícula: mientras más rojo, menos vecinos, a más blanco más. El detalle es que "más" y "menos" están definidos de manera relativa al valor máximo de densidad entre todas las partículas. Este valor de densidad es bastante simple de calcular (conceptualmente) pero un poco costoso.

Calculando la densidad

La forma más básica de calcular esta densidad es tan simple como:
[code language="cpp"]
void update_density(std::vector<Particle>& particles) {
    for (auto& p1 : particles) {
        for (auto& p2 : particles) {
            if (p1.dist2(p2) < THRESHOLD_DIST) {
                p1.density++;
            }
        }
    }
}
[/code]
Las dos cosas más importantes a notar acá son,

Hay un una gran cantidad de poder de cómputo perdido repitiendo operaciones.

El órden de ejecución de esta función es O(N^2) con N siendo la cantidad de partículas

No repetir trabajo

La primera aproximación a mejorar estos 2 problemas es muy simple e implica evitar hacer 2 veces los mismos cálculos. En cada iteración de la función, la misma partícula va a tomar la posición de p1 y luego p2 así que vamos a ejecutar, eventualmente p1.dist2(p2) y luego p2.dist2(p1). Evitemos esto:
[code language="cpp"]
void update_density(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        auto& p1 = particles[ix];
        for (auto jx = ix + 1; jx < particles.size(); jx++) {
            auto& p2 = particles[jx];
            if (p1.dist2(p2) < THRESHOLD_DIST) {
                p1.density++;
                p2.density++;
            }
        }
    }
}
[/code]
Con este pequeño cambio nos ahorramos el realizar muchos cálculos 2 veces, porque cada iteración actualiza la densidad de las dos partículas (y evitamos calcular de nuevo ambos valores comparando cada partícula solo con las siguientes en la lista).

Sin embargo, el orden de ejecución no cambia demasiado, ahora realizamos comparaciones en base a la siguiente serie:

El orden sigue siendo cuadrático. Necesitamos una forma de reducir la cantidad de cálculos que realizamos drásticamente.

Localidad del problema

Tratamos de visualizar la densidad de partículas en cada posición de cada partícula, lo que implica que necesitamos una valor de umbral lo sificientemente pequeño para que tenga algún sentido en la imagen final. Como tratamos de dibujar las partículas en la superficie de la esfera unitaria (una unidad de radio), la distancia máxima entre 2 partículas va a ser de 2 unidades (diámetro). Elegí como valor de umbral sqrt(0.004) ~ 0.063 (las pruebas se hacen con todas las distancias cuadradas para ahorrar el costo de realizar la raíz cuadrada), podría haber sido cualquier número, pero este resultó bien desde el principio.

Si uno compara ambos valores, se nota que muchas, MUCHAS partículas están muy lejos entre ellas, por lo que se puede utilizar una estructura de datos que sea útil para descartar la mayor cantidad posible de comparaciones aún antes de realizarlas. Estructuras de este tipo entran en la familia de árboles de división espacial como quadtrees, octrees, árboles BSP y kd-trees por nombrar algunos.
De hecho, en ray tracing usando la técnica de Photon Mapping, es muy común utilizar kd-trees como estructura básica del Photon Map por la calidad de las consultas de puntos por rangos de distancia (al consultar por los fotones en el área circundante a algún punto en el espacio).

El tema, es que se puede tornar costos mantener el kd-tree si las posiciones se agregan y quitan dinámicamete (el árbol termina necesitando re-balanceos muchas veces), como yo quería animar las partículas eventualmente, esto se tornó una inconveniencia.

Lo que terminé implementando es una versión hackeada-trucha, de un octree con tamaño de hojas fijo (cualquiera me puede argumentar que esto se podría haber licenciado bajo CRAPL en lugar de MIT, pero che, funcionó y fue bastante fácil ;P). En lugar de crear dinámicamente la estructura del árbol, definí 2 parámetros, la bounding box del modelo (solo a través de los valores máximo y mínimo que cualquier coordenada pueda tomar) y el número de intervalos en los que cada eje se va a subdividir.

La estructura básica es un hashmap de vectores (sets podrían haber funcionado también, capaz mejor...) donde cada key es el identificador generado a partir de la posición y el valor es un vector con todos los elementos que pertenecen a una hoja de esta cosa.

En lugar de comparar todas las partículas, una gran porción de las mismas es descartada sin problema y solo los mejores candidatos se utilizan en el proceso de comparación.

SPP o "Space Partitioned Positions"

Esta es la estructura aceleradora que utilicé:
[code language="cpp"]
class spp {
public:
    spp(uint8_t intervals_per_axis, float min_val, float max_val);
    ~spp() = default;

    uint32_t add(const glm::vec3& pos, size_t external_idx);
    void remove(const glm::vec3& pos, size_t external_idx);
    void remove(uint32_t bucket_id, size_t external_idx);
    std::vector<uint32_t> get_buckets_area(const glm::vec3& pos) const;
    std::vector<uint32_t> get_buckets_area(uint32_t bucket_id) const;
    const std::vector<size_t>& get_bucket(uint32_t bucket_id) const;
private:
    std::unordered_map<uint32_t, std::vector<size_t>> m_buckets;
    uint8_t m_intervals_per_axis;
    glm::vec3 m_min_vec;
    float m_normalize_value;

    uint32_t get_bucket(const glm::vec3& pos) const;
};
[/code]
Paso a paso:
[code language="cpp"]
spp::spp(const uint8_t intervals_per_axis, const float min_val, const float max_val)
    : m_intervals_per_axis(intervals_per_axis)
    , m_min_vec{ min_val, min_val, min_val }
    , m_normalize_value(max_val - min_val) {
    SPL_ASSERT(m_normalize_value != 0., "SPP interval can't be zero.");
    SPL_ASSERT(max_val > min_val, "Consider swapping min and max!");
}
[/code]
Este es el cosntructor, inicializa algunos miembros auxiliares y hace algunos controles simples. Estos miembros son un vector (solo para simplificar sintaxis, bien podría haber sido un valor solo) para el valor mínimo, otro para la cantidad de intervalos (con un máximo de 0xFF o 255 intervalos por eje) y un tercer valor para el largo de la boundinb box (por eje). (Por como funciona, tanto 0 como 1 en el número de intervalos resultan en el mismo efecto).
[code language="cpp"]
uint32_t spp::add(const glm::vec3& pos, const size_t external_idx) {
    const auto bid = get_bucket(pos);
    m_buckets[bid].push_back(external_idx);
    return bid;
}
[/code]
Este método agrega un elemento a la estructura, este elemento es referencioado con el external_idx (en mi caso estaba utilizando índices para referenciar cada partícula afuera) y la variable pos refiere a la posición de dicho elemento.

Como se ve, genera una key asociada al vector donde se almacenan los elementos usando la posición, guarda el id en el vector y finalmente retorna el identificador de este vector. Dado que calcular el id a partir de la posición es algo costoso, en el resto del código lo optimicé un poco almacenando este identificador en cada partícula. De todos modos esto no es necesario ya que siempre se puede obtener el identificador a partir de la posición.
[code language="cpp"]
void spp::remove(const glm::vec3& pos, const size_t external_idx) {
    remove(get_bucket(pos), external_idx);
}
void spp::remove(const uint32_t bucket_id, const size_t external_idx) {
    auto& b = m_buckets[bucket_id];
    b.erase(std::find(b.begin(), b.end(), external_idx));
}
[/code]
Luego vienen los métodos de quitar elementos, uno utilizando la posición y el otro directamente el identificador de la hoja/vector, Esta es la operación en la que uno podría argumentar que un set sería mejor 'hoja' que un vector, pero no he realizado ninguna comparación de performance como para justificar el cambio (otras partes del código podrían funcionar peor con un set, a causa de cache misses y localidad de datos).

Bueno, finalmente el método intersante, get_bucket:
[code language="cpp"]
uint32_t spp::get_bucket(const glm::vec3& pos) const {
    const auto norm = (pos - m_min_vec) / m_normalize_value;
    return pack(
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.x)),
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.y)),
        static_cast<uint8_t>(std::floor(m_intervals_per_axis * norm.z)));
}
[/code]
Pueden ver lo que se hace, cada coordenada es mapeada al intervalo [0, 1] usando los parámetros del constructor y luego el valor obtenido se utiliza para generar un uint8_t por cada coordenada basado en la cantidad de intervalos. Finalmente los 3 valores se empacan en un solo uint32_t usando el método pack.

¿Cómo funciona? Pensémoslo en una sola dimensión:

Usando 8 como el número de intervalos (intervals_per_axis), supongamos que recibimos pos = -0.3:

Así que el identificador de la hoja es 2.
Haciendo lo mismo para 0.5 tenemos: id = 6. Y finalmente, usando un valor muy cercano a 0.5 deberíamos obtener o bien el mismo identificador o uno contiguo, para 0.55 -> 6, para 0.45 -> 5, para 0.75 -> 7. Estamos dividiendo el intervalo original en otros más pequeños cuyo largo es igual al largo de la bounding box (por eje) dividido por el número de intervalos y asignando identificadores basados en dentro de cuál subintervalo cae.

Si alguna vez leyeron sobre scalar quantization o empaquetado de floats (como para los canales de colores) esto es lo mismo.

El resultado general es que:

Es un hecho que la distancia máxima entre elementos dentro de la misma hoja es igual a:

Desafortunadamente eso no significa que una sola hoja es suficiente para calcular la densidad alrededor de cada partícula, dado que 2 partículas muy cercanas podrían terminar en hojas aledañas pero...

Se pueden obtener todas las partículas que están dentro de un radio X utilizando la hoja en la que cayó la partícula y todas las hojas vecinas, siempre y cuando X sea menor que m_normalize_value/m_intervals_per_axis.

En nuestro caso unidimensional, la distancia máxima entre 2 valores dentro de la misma hoja es 0.25, y tomando cualquier posición P dentro de la hoja H, se pueden calcular todas las posiciónes con una distancia a P menor a 0.25 analizando solo las partículas en las hojas B, B-1 (si B != 0) y B+1 (si B != 7). Al dividir nuestro set original en 8, se reducen la cantidad de posiciones a analizar a aquellas que estén dentro de 3 de las 8 hojas (en el peor caso).

Prosiguiendo:
[code language="cpp"]
std::vector<uint32_t> spp::get_buckets_area(const uint32_t bucket_id) const {
    std::vector<uint32_t> buckets;
    buckets.reserve(3 * 3 * 3); // Max adjacent buckets (think of a rubik's cube)
    const auto unpacked = unpack(bucket_id);
    for (int8_t ix = -1; ix < 2; ix++) {
        const int8_t xval = unpacked[0] + ix;
        if (xval >= 0 && xval < m_intervals_per_axis) {
            for (int8_t iy = -1; iy < 2; iy++) {
                const int8_t yval = unpacked[1] + iy;
                if (yval >= 0 && yval < m_intervals_per_axis) {
                    for (int8_t iz = -1; iz < 2; iz++) {
                        const int8_t zval = unpacked[2] + iz;
                        if (zval >= 0 && zval < m_intervals_per_axis) {
                            const auto potential_id = pack(xval, yval, zval);
                            if (m_buckets.find(potential_id) != m_buckets.end()) {
                                buckets.push_back(potential_id);
                            }
                        }
                    }
                }
            }
        }
    }
    return buckets;
}
[/code]
Este código nos permite detectar el set de hoja+vecinas calculando los valores válidos para cada parte del identificador empaquetado (imaginen el centro de un cubo rubik, y las posiciones de todas las restantes piezas). Dado un solo identificador obtenemos ese mismo ID y todos los de los 26 vecinos (en el peor caso). Finalmente, pack y unpack son métodos que empacan 3 (podrían ser 4) enteros de 8 bits en uno de 32.
[code language="cpp"]
static uint32_t pack(const uint8_t x, const uint8_t y, const uint8_t z) {
    return  x << 16 | y << 8 | z;
}
static std::array<uint8_t, 3> unpack(uint32_t value) {
    return{
        (value >> 16) & 0xFF,
        (value >> 8) & 0xFF,
        value & 0xFF
    };
}
[/code]

Usando el SPP

Una vez que el SPP está pronto, en lugar de computar la densidad calculando las distancias entre todas las partículas, podemos:

Agregar todas las partículas al SPP y luego,

Para cada partícula a actualizar obtenemos el set de hojas que son vecinas y,

Calcular la distancia a las partículas dentro de esas hojas únicamente:

[code language="cpp"]
void load_particles(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        // Note we store the bucket id outside to reduce the amount of times we need to calculate it later.
        p.bucket_id = spp.add(p.position, ix);
    }
}

void update_density(std::vector<Particle>& particles) {
    for (auto ix = 0u; ix < particles.size(); ix++) {
        auto& p1 = particles[ix];
        auto buckets = spp.get_buckets_area(p1.bucket_id);
        for (auto jx = 0u; jx < buckets.size(); jx++) {
            auto& bucket = spp.get_bucket(buckets[jx]);
            for (auto kx = 0u; kx < bucket.size(); kx++) {
                auto& p2 = particles[bucket[kx]];
                if (p1.dist2(p2) < THRESHOLD_DIST) {
                    p1.density++;
                }
            }
        }
    }
}
[/code]
Noten que nuevamente estoy repitiendo algo de trabajo, porque ya no actualizo la densidad de ambas partículas en la misma iteración, esto se debe a que ya no se puede asegurar el orden en el que las partículas van a ser visitadas, así que tratar de evitar este doble cálculo se vuelve más complicado. El ahorro de utilizar el spp justifica más que suficientemente por esto (y por la posible complejidad del algoritmo para saltearse correctamente las comparaciones ya realizadas).

Luego de esto, calcular el color de cada partícula es solo cosa de encontrar la densidad máxima y obtener un valor de RGBA basado en la proporción de densidad de cada partícula sobre el máximo. Yo utilicé algo parecido a esto:
[code language="cpp"]
Color color_for_particle(Particle& p, const uint32_t max_density) {
    float alive_value = p.isAlive() ? 1.f : 0.f; //Se podría castear simplemete :)
    return Color {
        alive_value,
        (p.density / max_density) * alive_value,
        (p.density / max_density) * alive_value,
        alive_value
    };
}
[/code]
Si analizan la historia del repositorio, pueden ver que en un principio calculaba el color en el CPU y luego se forwardeaba directamente al shader. Obviamente esto no es la mejor opción, en la versión actual, solo el valor máximo se calcula en el CPU y luego es pasado como un uniform, y la densidad por partícula se pasa como otro atributo. De esta manera, el cálculo se puede realizar en el GPU.

Azul, Rojo y la distancia al centro

En esta demo, los cálculos son más simples, nada se realiza en el CPU y el shader genera rojo si la distancia de la partícula al centro es menor a 1 y azul si no.
[code language="cpp"]
Color color_for_particle_blue(Particle& p) {
    float alive_value = p.isAlive() ? 1.f : 0.f; //Se podría castear simplemete :)
    float r = (p.length <= 1.) ? 1.f : 0.f; //Se podría castear simplemete :)
    return Color {
        r,
        0.f,
        1.f - r,
        alive_value
    };
}
[/code]

Nota al pie sobre el número de intervalos en el SPP

El número de hojas influencia directamente la cantidad de comparaciones que debemos realizar pero además la distancia máxima que dos partículas pueden tener. Necesitamos instanciar el SPP con el valor correcto para saltear el mayor número de comparaciones entre partículas sin perdernos ninguna de las partículas que deben ser parte del cálculo de densidad. Para caulcular esta densidad hay que 'encerrar' el volumen de cercanía alrededor de la partícula en el cubo creado por la hoja a la que la partícula pertenece y todas las hojas vecinas:

Habiendo elegido un umbral igual a srqr(0.004) ~ 0.0632 es necesario un tamaño por hoja (por eje) por lo menos de ese valor.

Sabemos que el valor máximo de coordenadas es uno y el mínimo es -1, así que la bounding box tiene 2 unidades de largo por eje

Este número de intervalos por eje nos da un tamaño de hoja (por eje) de ~0.645 unidades, el valor más pequeño no menor al umbral. Esto asegura que aún el peor caso queda cubierto, y todas las particulas que pueden contribuir al valor de densidad de una partícula dada son evaluadas.

El peor caso, está dado por una partícula que cae en el plano de borde de una hoja. Pensando nuevamente en el caso unidimensional, si el umbral fuese 0.26, tener 8 intervalos es demasiado: una muestra con la posición 0.5 termina en la hoja 6, y una muestra con la posición 0.245 termina en la hoja 4. Estas dos muestras no se van a comparar porque no están en hojas vecinas aún cuando la distancia entre ellas es menor a 0.26.

¡Fin! ¡Bien! Terminaste un artícula largo sobre los detalles de una demo sin importancia, ¡felicidades! Por lo menos espero que le hayas sacado algún provecho. Podés referirte al artículo previo para ver la historia original y el código fuente.
Inicio


text:
function prepare-package-manager() {
  echo "Prepare package manager"

  # Useful if a mirror is broken or slow
  echo "fastestmirror=True" >> /etc/dnf/dnf.conf

  # In Fedora 23, installed version does not work with Salt
  # Cf. https://github.com/saltstack/salt/issues/31001
  dnf update -y dnf dnf-plugins-core
}

function add-volume-support() {
  echo "Adding nfs volume support"

  # we need nfs-utils to support volumes
  dnf install -y nfs-utils
}

function write-salt-config() {
  local role="$1"

  # Update salt configuration
  mkdir -p /etc/salt/minion.d

  mkdir -p /srv/salt-overlay/pillar
  cat <<EOF >/srv/salt-overlay/pillar/cluster-params.sls
service_cluster_ip_range: '$(echo "$SERVICE_CLUSTER_IP_RANGE" | sed -e "s/'/''/g")'
cert_ip: '$(echo "$MASTER_IP" | sed -e "s/'/''/g")'
enable_cluster_monitoring: '$(echo "$ENABLE_CLUSTER_MONITORING" | sed -e "s/'/''/g")'
enable_cluster_logging: '$(echo "$ENABLE_CLUSTER_LOGGING" | sed -e "s/'/''/g")'
enable_cluster_ui: '$(echo "$ENABLE_CLUSTER_UI" | sed -e "s/'/''/g")'
enable_node_logging: '$(echo "$ENABLE_NODE_LOGGING" | sed -e "s/'/''/g")'
logging_destination: '$(echo "$LOGGING_DESTINATION" | sed -e "s/'/''/g")'
elasticsearch_replicas: '$(echo "$ELASTICSEARCH_LOGGING_REPLICAS" | sed -e "s/'/''/g")'
enable_cluster_dns: '$(echo "$ENABLE_CLUSTER_DNS" | sed -e "s/'/''/g")'
dns_replicas: '$(echo "$DNS_REPLICAS" | sed -e "s/'/''/g")'
dns_server: '$(echo "$DNS_SERVER_IP" | sed -e "s/'/''/g")'
dns_domain: '$(echo "$DNS_DOMAIN" | sed -e "s/'/''/g")'
instance_prefix: '$(echo "$INSTANCE_PREFIX" | sed -e "s/'/''/g")'
admission_control: '$(echo "$ADMISSION_CONTROL" | sed -e "s/'/''/g")'
enable_cpu_cfs_quota: '$(echo "$ENABLE_CPU_CFS_QUOTA" | sed -e "s/'/''/g")'
network_provider: '$(echo "$NETWORK_PROVIDER" | sed -e "s/'/''/g")'
cluster_cidr: '$(echo "$CLUSTER_IP_RANGE" | sed -e "s/'/''/g")'
opencontrail_tag: '$(echo "$OPENCONTRAIL_TAG" | sed -e "s/'/''/g")'
opencontrail_kubernetes_tag: '$(echo "$OPENCONTRAIL_KUBERNETES_TAG" | sed -e "s/'/''/g")'
opencontrail_public_subnet: '$(echo "$OPENCONTRAIL_PUBLIC_SUBNET" | sed -e "s/'/''/g")'
e2e_storage_test_environment: '$(echo "$E2E_STORAGE_TEST_ENVIRONMENT" | sed -e "s/'/''/g")'
EOF

  cat <<EOF >/etc/salt/minion.d/log-level-debug.conf
log_level: warning
log_level_logfile: warning
EOF

  cat <<EOF >/etc/salt/minion.d/grains.conf
grains:
  node_ip: '$(echo "$MASTER_IP" | sed -e "s/'/''/g")'
  publicAddressOverride: '$(echo "$MASTER_IP" | sed -e "s/'/''/g")'
  network_mode: openvswitch
  networkInterfaceName: '$(echo "$NETWORK_IF_NAME" | sed -e "s/'/''/g")'
  api_servers: '$(echo "$MASTER_IP" | sed -e "s/'/''/g")'
  cloud: vagrant
  roles:
    - $role
  runtime_config: '$(echo "$RUNTIME_CONFIG" | sed -e "s/'/''/g")'
  docker_opts: '$(echo "$DOCKER_OPTS" | sed -e "s/'/''/g")'
  master_extra_sans: '$(echo "$MASTER_EXTRA_SANS" | sed -e "s/'/''/g")'
  keep_host_etcd: true
EOF
}

function install-salt() {
  server_binary_tar="/vagrant/server/kubernetes-server-linux-amd64.tar.gz"
  if [[ ! -f "$server_binary_tar" ]]; then
    server_binary_tar="/vagrant/_output/release-tars/kubernetes-server-linux-amd64.tar.gz"
  fi
  if [[ ! -f "$server_binary_tar" ]]; then
    release_not_found
  fi

  salt_tar="/vagrant/server/kubernetes-salt.tar.gz"
  if [[ ! -f "$salt_tar" ]]; then
    salt_tar="/vagrant/_output/release-tars/kubernetes-salt.tar.gz"
  fi
  if [[ ! -f "$salt_tar" ]]; then
    release_not_found
  fi

  echo "Running release install script"
  rm -rf /kube-install
  mkdir -p /kube-install
  pushd /kube-install
  tar xzf "$salt_tar"
  cp "$server_binary_tar" .
  ./kubernetes/saltbase/install.sh "${server_binary_tar##*/}"
  popd

  if ! which salt-call >/dev/null 2>&1; then
    # Install salt binaries
    curl -sS -L --connect-timeout 20 --retry 6 --retry-delay 10 https://bootstrap.saltstack.com | sh -s

    # Fedora >= 23 includes salt packages but the bootstrap is
    # creating configuration for a (non-existent) salt repo anyway.
    # Remove the invalid repo to prevent dnf from warning about it on
    # every update.  Assume this problem is specific to Fedora 23 and
    # will fixed by the time another version of Fedora lands.
    local fedora_version=$(grep 'VERSION_ID' /etc/os-release | sed 's+VERSION_ID=++')
    if [[ "${fedora_version}" = '23' ]]; then
      local repo_file='/etc/yum.repos.d/saltstack-salt-fedora-23.repo'
      if [[ -f "${repo_file}" ]]; then
        rm "${repo_file}"
      fi
    fi

  fi
}

function run-salt() {
  echo "  Now waiting for the Salt provisioning process to complete on this machine."
  echo "  This can take some time based on your network, disk, and cpu speed."
  salt-call --local state.highstate
}

function create-salt-kubelet-auth() {
  local -r kubelet_kubeconfig_folder="/srv/salt-overlay/salt/kubelet"
  mkdir -p "${kubelet_kubeconfig_folder}"
  (umask 077;
  cat > "${kubelet_kubeconfig_folder}/kubeconfig" << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
    insecure-skip-tls-verify: true
  name: local
contexts:
- context:
    cluster: local
    user: kubelet
  name: service-account-context
current-context: service-account-context
users:
- name: kubelet
  user:
    token: ${KUBELET_TOKEN}
EOF
  )
}

function create-salt-kubeproxy-auth() {
  kube_proxy_kubeconfig_folder="/srv/salt-overlay/salt/kube-proxy"
  mkdir -p "${kube_proxy_kubeconfig_folder}"
  (umask 077;
  cat > "${kube_proxy_kubeconfig_folder}/kubeconfig" << EOF
apiVersion: v1
kind: Config
clusters:
- cluster:
    insecure-skip-tls-verify: true
  name: local
contexts:
- context:
    cluster: local
    user: kube-proxy
  name: service-account-context
current-context: service-account-context
users:
- name: kube-proxy
  user:
    token: ${KUBE_PROXY_TOKEN}
EOF
  )
}


text:
<!DOCTYPE html>

<meta charset="utf-8">
<title>WebGL GLSL Conformance Tests</title>
<link rel="stylesheet" href="./resources/js-test-style.css"/>
<link rel="stylesheet" href="./resources/glsl-feature-tests.css"/>


text:
import { createSelector } from 'reselect';

import { ESDBStatus, ES_EXTRA_RESULTS_LIMIT } from '@proton/encrypted-search';
import { LabelCount } from '@proton/shared/lib/interfaces';
import isTruthy from '@proton/utils/isTruthy';

import {
    DEFAULT_PLACEHOLDERS_COUNT,
    ELEMENTS_CACHE_REQUEST_SIZE,
    MAX_ELEMENT_LIST_LOAD_RETRIES,
    PAGE_SIZE,
} from '../../constants';
import { hasLabel, isFilter, isSearch, isUnread, sort as sortElements } from '../../helpers/elements';
import { expectedPageLength } from '../../helpers/paging';
import { ESMessage, NormalizedSearchParams } from '../../models/encryptedSearch';
import { SearchParameters } from '../../models/tools';
import { RootState } from '../store';
import { ElementsStateParams } from './elementsTypes';
import { getTotal } from './helpers/elementTotal';

const beforeFirstLoad = (state: RootState) => state.elements.beforeFirstLoad;
export const elementsMap = (state: RootState) => state.elements.elements;
export const params = (state: RootState) => state.elements.params;
const page = (state: RootState) => state.elements.page;
const pages = (state: RootState) => state.elements.pages;
const bypassFilter = (state: RootState) => state.elements.bypassFilter;
const pendingRequest = (state: RootState) => state.elements.pendingRequest;
export const pendingActions = (state: RootState) => state.elements.pendingActions;
const retry = (state: RootState) => state.elements.retry;
const invalidated = (state: RootState) => state.elements.invalidated;
const total = (state: RootState) => state.elements.total;
export const taskRunning = (state: RootState) => state.elements.taskRunning;

const currentPage = (_: RootState, { page }: { page: number }) => page;
const currentSearch = (_: RootState, { search }: { search: SearchParameters }) => search;
const currentParams = (_: RootState, { params }: { params: ElementsStateParams }) => params;
const currentESDBStatus = (
    _: RootState,
    { esDBStatus }: { esDBStatus: ESDBStatus<ESMessage, NormalizedSearchParams> }
) => esDBStatus;
const currentCounts = (_: RootState, { counts }: { counts: { counts: LabelCount[]; loading: boolean } }) => counts;

export const elements = createSelector(
    [elementsMap, params, page, pages, bypassFilter],
    (elements, params, page, pages, bypassFilter) => {
        // Getting all params from the cache and not from scoped params
        // To prevent any desynchronization between cache and the output of the memo
        const { labelID, sort, filter } = params;

        const minPage = pages.reduce((acc, page) => (page < acc ? page : acc), pages[0]);
        const startIndex = (page - minPage) * PAGE_SIZE;
        const endIndex = startIndex + PAGE_SIZE;
        const elementsArray = Object.values(elements);
        const filtered = elementsArray
            .filter((element) => hasLabel(element, labelID))
            .filter((element) => {
                if (!isFilter(filter)) {
                    return true;
                }
                if (bypassFilter.includes(element.ID || '')) {
                    return true;
                }
                const elementUnread = isUnread(element, labelID);
                return filter.Unread ? elementUnread : !elementUnread;
            });
        const sorted = sortElements(filtered, sort, labelID);

        return sorted.slice(startIndex, endIndex);
    }
);

export const elementIDs = createSelector(elements, (elements): string[] =>
    elements.map((element) => element.ID).filter(isTruthy)
);

export const elementsLength = createSelector(elements, (elements) => elements.length);

export const elementsAreUnread = createSelector([params, elements], (params, elements) => {
    return elements.reduce<{ [elementID: string]: boolean }>((acc, element) => {
        acc[element.ID] = isUnread(element, params.labelID);
        return acc;
    }, {});
});

/**
 * Define when we need to request the API to get more elements
 * Dynamic computations (dynamicTotal and dynamicPageLength) have been proved not to be reliable enough
 * So the logic here is a lot more basic
 * It only checks when there is not a full page to show if the label has more than a cache size of elements
 * It doesn't rely at all on the optimistic counter logic
 */
export const needsMoreElements = createSelector([total, page, elementsLength], (total, page, elementsLength) => {
    if (total === undefined) {
        return false;
    }
    const howManyElementsAhead = total - page * PAGE_SIZE;
    return elementsLength < PAGE_SIZE && howManyElementsAhead > ELEMENTS_CACHE_REQUEST_SIZE;
});

export const paramsChanged = createSelector([params, currentParams], (params, currentParams) => {
    const paramsChanged =
        currentParams.labelID !== params.labelID ||
        currentParams.conversationMode !== params.conversationMode ||
        currentParams.sort !== params.sort ||
        currentParams.filter !== params.filter ||
        currentParams.search !== params.search ||
        (currentParams.esEnabled !== params.esEnabled && isSearch(currentParams.search));
    return paramsChanged;
});

export const pageCached = createSelector([pages, currentPage], (pages, currentPage) => pages.includes(currentPage));

export const pageChanged = createSelector([page, currentPage], (page, currentPage) => page !== currentPage);

export const pageIsConsecutive = createSelector(
    [pages, currentPage],
    (pages, currentPage) =>
        pages.length === 0 || pages.some((p) => p === currentPage || p === currentPage - 1 || p === currentPage + 1)
);

export const shouldResetCache = createSelector(
    [paramsChanged, pageIsConsecutive],
    (paramsChanged, pageIsConsecutive) => {
        return paramsChanged || !pageIsConsecutive;
    }
);

export const shouldSendRequest = createSelector(
    [shouldResetCache, pendingRequest, retry, needsMoreElements, invalidated, pageCached],
    (shouldResetCache, pendingRequest, retry, needsMoreElements, invalidated, pageCached) => {
        return (
            shouldResetCache ||
            (!pendingRequest &&
                retry.count < MAX_ELEMENT_LIST_LOAD_RETRIES &&
                (needsMoreElements || invalidated || !pageCached))
        );
    }
);

export const isLive = createSelector([params, pages], (params, pages) => !isSearch(params.search) && pages.includes(0));

export const shouldUpdatePage = createSelector(
    [pageChanged, pageCached],
    (pageChanged, pageCached) => pageChanged && pageCached
);

export const isES = createSelector(
    [currentESDBStatus, currentSearch],
    ({ dbExists, esEnabled, isCacheLimited }, search) =>
        dbExists && esEnabled && isSearch(search) && (!!search.keyword || !isCacheLimited)
);

/**
 * Loading more search results using ES should be done only under the
 * following circumstances:
 *  - ES is being used for the search;
 *  - the cache is limited, i.e. the local index is too large to safely fit
 *    in memory and there are messages which are only stored on disk;
 *  - the search is partial, meaning that the whole index on disk hasn't been
 *    fully searched yet;
 *  - a new page of results has been queried by the user's navigation;
 *  - the total number of messages in the results list is not enough to fill
 *    at least the current and the subsequent pages
 */
export const messagesToLoadMoreES = createSelector(
    [currentESDBStatus, isES, pageChanged, total, currentPage],
    ({ isCacheLimited, isSearchPartial }, useES, pageChanged, total, currentPage) => {
        if (
            useES &&
            isCacheLimited &&
            isSearchPartial &&
            pageChanged &&
            (total || 0) < (currentPage + 2) * ES_EXTRA_RESULTS_LIMIT
        ) {
            return (currentPage + 2) * ES_EXTRA_RESULTS_LIMIT - (total || 0);
        }
        return 0;
    }
);

/**
 * Computed up to date total of elements for the current parameters
 * Warning: this value has been proved not to be 100% consistent
 * Has to be used only for non sensitive behaviors
 */
export const dynamicTotal = createSelector([params, currentCounts], (params, { counts, loading }) => {
    if (isSearch(params.search) || loading) {
        return undefined;
    }
    return getTotal(counts, params.labelID, params.filter);
});

/**
 * Computed up to date number of elements on the current page
 * Warning: this value has been proved not to be 100% consistent
 * Has to be used only for non sensitive behaviors
 */
export const dynamicPageLength = createSelector(
    [page, dynamicTotal, params, bypassFilter],
    (page, dynamicTotal, params, bypassFilter) => {
        if (dynamicTotal === undefined) {
            return undefined;
        }
        return expectedPageLength(page, dynamicTotal, isFilter(params.filter) ? bypassFilter.length : 0);
    }
);

export const placeholderCount = createSelector(
    [page, total, params, dynamicPageLength],
    (page, total, params, dynamicPageLength) => {
        if (dynamicPageLength !== undefined) {
            return dynamicPageLength;
        }
        if (total !== undefined) {
            return expectedPageLength(page, total, isFilter(params.filter) ? bypassFilter.length : 0);
        }
        return DEFAULT_PLACEHOLDERS_COUNT;
    }
);

export const loading = createSelector(
    [beforeFirstLoad, pendingRequest, shouldSendRequest, invalidated],
    (beforeFirstLoad, pendingRequest, shouldSendRequest, invalidated) =>
        (beforeFirstLoad || pendingRequest || shouldSendRequest) && !invalidated
);

export const totalReturned = createSelector([dynamicTotal, total], (dynamicTotal, total) => dynamicTotal || total);

export const expectingEmpty = createSelector([dynamicPageLength], (dynamicPageLength) => dynamicPageLength === 0);

export const loadedEmpty = createSelector(
    [beforeFirstLoad, pendingRequest, total],
    (beforeFirstLoad, pendingRequest, total) => !beforeFirstLoad && pendingRequest === false && total === 0
);

export const partialESSearch = createSelector(
    [isES, currentESDBStatus],
    (useES, currentESDBStatus) => useES && currentESDBStatus.isCacheLimited && currentESDBStatus.isSearchPartial
);

export const stateInconsistency = createSelector(
    [beforeFirstLoad, pendingRequest, retry, isES],
    (beforeFirstLoad, pendingRequest, retry, useES) =>
        !beforeFirstLoad && !pendingRequest && retry.error === undefined && retry.count === 3 && !useES
);

export const showLabelTaskRunningBanner = createSelector([taskRunning], (taskRunning) => {
    return taskRunning.labelIDs.length > 0;
});


text:
package org.springframework.security.oauth.examples.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

/**
 * @author Dave Syer
 */
public class ServletInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SecurityConfig.class, WebMvcConfig.class);
        return context;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        registerProxyFilter(servletContext, "springSecurityFilterChain");
        registerProxyFilter(servletContext, "oauth2ClientContextFilter");
    }

    private void registerProxyFilter(ServletContext servletContext, String name) {
        DelegatingFilterProxy filter = new DelegatingFilterProxy(name);
        filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
        servletContext.addFilter(name, filter).addMappingForUrlPatterns(null, false, "/*");
    }

}


text:
import { CREATE_WHITEBOARD_ITEM_COMPLETE, DELETE_WHITEBOARD_ITEM_COMPLETE, DELETE_WHITEBOARD_ITEM_ATTEMPT,
  UPVOTE_WHITEBOARD_ITEM_COMPLETE, DOWNVOTE_WHITEBOARD_ITEM_COMPLETE, DEVOTE_WHITEBOARD_ITEM_COMPLETE } from '../../action-types/whiteboarding/constants';

import { VOTE_STATUS } from '../../well_known_constants/enums';

/* Define your initial state here.
 *
 * If you change the type from object to something else, do not forget to update
 * src/container/App.js accordingly.
 */
const initialState = {
  items: [
    {
      id: 0,
      description: 'Hello world',
      upvotes: [{id:0}],
      downvotes: [{id:1}],
      dateAdded: Date(),
      minRatio: [300, 300],
      maxRatio: [300, 300],
      voteStatus: VOTE_STATUS.NONE,
      attemptingToDelete: false
    }
  ]
};

module.exports = function(state = initialState, action) {
  /* Keep the reducer clean - do not mutate the original state. */
  //let nextState = Object.assign({}, state);

  switch(action.type) {
    /*
    case 'YOUR_ACTION': {
      // Modify next state depending on the action and return it
      return nextState;
    } break;
    */
  case CREATE_WHITEBOARD_ITEM_COMPLETE: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.concat(action.item),
        addingAnItem: false
      }
    );
    return nextState;
  }
  case DELETE_WHITEBOARD_ITEM_ATTEMPT: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.map(item => {
          return Object.assign({}, item, item.id === action.itemId ? {attemptingToDelete: true} : {});
        })
      });
    return nextState;
  }
  case DELETE_WHITEBOARD_ITEM_COMPLETE: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.filter(item => item.id !== action.itemId)
      }
    );
    return nextState;
  }
  case UPVOTE_WHITEBOARD_ITEM_COMPLETE: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.map((item) => {
          if (item.id === action.itemId) {
            return Object.assign({}, item, {
              downvotes: item.downvotes.filter(vote=>vote.id!==action.userId),
              upvotes: item.upvotes.concat({id: action.userId}),
              voteStatus: VOTE_STATUS.UPVOTED
            });
          }
          return Object.assign({}, item);
        })
      }
    );
    return nextState;
  }
  case DOWNVOTE_WHITEBOARD_ITEM_COMPLETE: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.map((item)=> {
          if (item.id===action.itemId) {
            return Object.assign({}, item, {
              downvotes: item.downvotes.concat({id: action.userId}),
              upvotes: item.upvotes.filter(vote=>vote.id!==action.userId),
              voteStatus: VOTE_STATUS.DOWNVOTED
            });
          }
          return Object.assign({}, item);
        })
      }
    );
    return nextState;
  }
  case DEVOTE_WHITEBOARD_ITEM_COMPLETE: {
    let nextState = Object.assign({},
      state,
      {
        items: state.items.map((item)=> {
          if (item.id===action.itemId) {
            return Object.assign({}, item, {
              downvotes: item.downvotes.filter(vote=>vote.id!==action.userId),
              upvotes: item.upvotes.filter(vote=>vote.id!==action.userId),
              voteStatus: VOTE_STATUS.NONE
            });
          }
          return Object.assign({}, item);
        })
      });
    return nextState;
  }
  default: {
    /* Return original state if no actions were consumed. */
    return state;
  }
  }
};


text:
module ActiveMerchant #:nodoc:
  module Billing #:nodoc:
    # See the remote and mocked unit test files for example usage.  Pay special attention to the contents of the options hash.
    #
    # Initial setup instructions can be found in http://cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf
    #
    # Debugging
    # If you experience an issue with this gateway be sure to examine the transaction information from a general transaction search inside the CyberSource Business
    # Center for the full error messages including field names.
    #
    # Important Notes
    # * AVS and CVV only work against the production server.  You will always get back X for AVS and no response for CVV against the test server.
    # * Nexus is the list of states or provinces where you have a physical presence.  Nexus is used to calculate tax.  Leave blank to tax everyone.
    # * If you want to calculate VAT for overseas customers you must supply a registration number in the options hash as vat_reg_number.
    # * productCode is a value in the line_items hash that is used to tell CyberSource what kind of item you are selling.  It is used when calculating tax/VAT.
    # * All transactions use dollar values.
    class CyberSourceGateway < Gateway
      TEST_URL = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
      LIVE_URL = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'

      # visa, master, american_express, discover
      self.supported_cardtypes = [:visa, :master, :american_express, :discover]
      self.supported_countries = ['US']
      self.default_currency = 'USD'
      self.homepage_url = 'http://www.cybersource.com'
      self.display_name = 'CyberSource'

      # map credit card to the CyberSource expected representation
      @@credit_card_codes = {
        :visa  => '001',
        :master => '002',
        :american_express => '003',
        :discover => '004'
      }

      # map response codes to something humans can read
      @@response_codes = {
        :r100 => "Successful transaction",
        :r101 => "Request is missing one or more required fields" ,
        :r102 => "One or more fields contains invalid data",
        :r150 => "General failure",
        :r151 => "The request was received but a server time-out occurred",
        :r152 => "The request was received, but a service timed out",
        :r200 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check",
        :r201 => "The issuing bank has questions about the request",
        :r202 => "Expired card",
        :r203 => "General decline of the card",
        :r204 => "Insufficient funds in the account",
        :r205 => "Stolen or lost card",
        :r207 => "Issuing bank unavailable",
        :r208 => "Inactive card or card not authorized for card-not-present transactions",
        :r209 => "American Express Card Identifiction Digits (CID) did not match",
        :r210 => "The card has reached the credit limit",
        :r211 => "Invalid card verification number",
        :r221 => "The customer matched an entry on the processor's negative file",
        :r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check",
        :r231 => "Invalid account number",
        :r232 => "The card type is not accepted by the payment processor",
        :r233 => "General decline by the processor",
        :r234 => "A problem exists with your CyberSource merchant configuration",
        :r235 => "The requested amount exceeds the originally authorized amount",
        :r236 => "Processor failure",
        :r237 => "The authorization has already been reversed",
        :r238 => "The authorization has already been captured",
        :r239 => "The requested transaction amount must match the previous transaction amount",
        :r240 => "The card type sent is invalid or does not correlate with the credit card number",
        :r241 => "The request ID is invalid",
        :r242 => "You requested a capture, but there is no corresponding, unused authorization record.",
        :r243 => "The transaction has already been settled or reversed",
        :r244 => "The bank account number failed the validation check",
        :r246 => "The capture or credit is not voidable because the capture or credit information has already been submitted to your processor",
        :r247 => "You requested a credit for a capture that was previously voided",
        :r250 => "The request was received, but a time-out occurred with the payment processor",
        :r254 => "Your CyberSource account is prohibited from processing stand-alone refunds",
        :r255 => "Your CyberSource account is not configured to process the service in the country you specified"
      }

      # These are the options that can be used when creating a new CyberSource Gateway object.
      #
      # :login =>  your username
      #
      # :password =>  the transaction key you generated in the Business Center
      #
      # :test => true   sets the gateway to test mode
      #
      # :vat_reg_number => your VAT registration number
      #
      # :nexus => "WI CA QC" sets the states/provinces where you have a physical presense for tax purposes
      #
      # :ignore_avs => true   don't want to use AVS so continue processing even if AVS would have failed
      #
      # :ignore_cvv => true   don't want to use CVV so continue processing even if CVV would have failed
      def initialize(options = {})
        requires!(options, :login, :password)
        @options = options
        super
      end

      # Should run against the test servers or not?
      def test?
        @options[:test] || Base.gateway_mode == :test
      end

      # Request an authorization for an amount from CyberSource
      #
      # You must supply an :order_id in the options hash
      def authorize(money, creditcard, options = {})
        requires!(options,  :order_id, :email)
        setup_address_hash(options)
        commit(build_auth_request(money, creditcard, options), options )
      end

      # Capture an authorization that has previously been requested
      def capture(money, authorization, options = {})
        setup_address_hash(options)
        commit(build_capture_request(money, authorization, options), options)
      end

      # Purchase is an auth followed by a capture
      # You must supply an order_id in the options hash
      def purchase(money, creditcard, options = {})
        requires!(options, :order_id, :email)
        setup_address_hash(options)
        commit(build_purchase_request(money, creditcard, options), options)
      end

      def void(identification, options = {})
        commit(build_void_request(identification, options), options)
      end

      def credit(money, identification, options = {})
        commit(build_credit_request(money, identification, options), options)
      end

      def create_subscription(creditcard, options = {})
        requires!(options, :subscription, :billing_address, :order_id, :email)
        requires!(options[:subscription], [:frequency, "on-demand", "weekly", "bi-weekly", "semi-monthly", "quarterly", "quad-weekly", "semi-annually", "annually"],:start_date, :occurrences, :auto_renew)
        requires!(options[:billing_address], :first_name, :last_name)
        setup_address_hash(options)
        commit(build_create_subscription_request(creditcard, options), options)
      end

      def update_subscription(identification, options = {})
        requires!(options, :order_id)
        setup_address_hash(options)
        commit(build_update_subscription_request(identification, options), options)
      end

      def retrieve_subscription(identification, options = {})
       commit(build_retrieve_subscription_request(identification, options), options)
      end

      def subscription_authorization(money, identification, options = {})
        commit(build_subscription_authorization_request(money, identification, options), options)
      end

      def subscription_purchase(money, identification, options = {})
        commit(build_subscription_purchase_request(money, identification, options), options)
      end

      # CyberSource requires that you provide line item information for tax calculations
      # If you do not have prices for each item or want to simplify the situation then pass in one fake line item that costs the subtotal of the order
      #
      # The line_item hash goes in the options hash and should look like
      #
      #         :line_items => [
      #           {
      #             :declared_value => '1',
      #             :quantity => '2',
      #             :code => 'default',
      #             :description => 'Giant Walrus',
      #             :sku => 'WA323232323232323'
      #           },
      #           {
      #             :declared_value => '6',
      #             :quantity => '1',
      #             :code => 'default',
      #             :description => 'Marble Snowcone',
      #             :sku => 'FAKE1232132113123'
      #           }
      #         ]
      #
      # This functionality is only supported by this particular gateway may
      # be changed at any time
      def calculate_tax(creditcard, options)
        requires!(options,  :line_items)
        setup_address_hash(options)
        commit(build_tax_calculation_request(creditcard, options), options)
      end

      private
      # Create all address hash key value pairs so that we still function if we were only provided with one or two of them
      def setup_address_hash(options)
        options[:billing_address] = options[:billing_address] || options[:address] || {}
        options[:shipping_address] = options[:shipping_address] || {}
      end

      def build_auth_request(money, creditcard, options)
        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options)
        add_address(xml, options[:shipping_address], options, true) if options[:shipping_address]
        add_purchase_data(xml, money, true, options)
        add_creditcard(xml, creditcard)
        add_auth_service(xml)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_tax_calculation_request(creditcard, options)
        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options)
        add_address(xml, options[:shipping_address], options, true) if options[:shipping_address]
        add_line_item_data(xml, options)
        add_purchase_data(xml, 0, false, options)
        add_tax_service(xml)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_capture_request(money, authorization, options)
        order_id, request_id, request_token = authorization.split(";")
        options[:order_id] = order_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_capture_service(xml, request_id, request_token)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_purchase_request(money, creditcard, options)
        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options)
        add_address(xml, options[:shipping_address], options, true) if options[:shipping_address]
        add_purchase_data(xml, money, true, options)
        add_creditcard(xml, creditcard)
        add_purchase_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_void_request(identification, options)
        order_id, request_id, request_token = identification.split(";")
        options[:order_id] = order_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_void_service(xml, request_id, request_token)
        xml.target!
      end

      def build_credit_request(money, identification, options)
        order_id, request_id, request_token = identification.split(";")
        options[:order_id] = order_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_credit_service(xml, request_id, request_token)

        xml.target!
      end

      def build_create_subscription_request(creditcard, options)
        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options)
        add_address(xml, options[:shipping_address], options, true)
        add_purchase_data(xml, options[:subscription][:amount], options[:setup_fee], options)
        add_creditcard(xml, creditcard)
        add_subscription(xml, options)
        add_subscription_create_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_update_subscription_request(identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options) unless options[:billing_address].empty?
        add_address(xml, options[:shipping_address], options, true) unless options[:shipping_address].empty?
        add_purchase_data(xml, options[:subscription][:amount], options[:setup_fee], options)
        add_creditcard(xml, options[:credit_card]) if options[:credit_card]
        add_subscription(xml, options)
        add_subscription_update_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_retrieve_subscription_request(identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id
        xml = Builder::XmlMarkup.new :indent => 2
        add_subscription(xml, options)
        add_subscription_retrieve_service(xml, options)
        xml.target!
      end

      def build_subscription_authorization_request(money, identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_subscription(xml, options)
        add_auth_service(xml)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_subscription_purchase_request(money, identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_subscription(xml, options)
        add_purchase_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_create_subscription_request(creditcard, options)
        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options)
        add_address(xml, options[:shipping_address], options, true)
        add_purchase_data(xml, options[:subscription][:amount], options[:setup_fee], options)
        add_creditcard(xml, creditcard)
        add_subscription(xml, options)
        add_subscription_create_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_update_subscription_request(identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_address(xml, options[:billing_address], options) unless options[:billing_address].empty?
        add_address(xml, options[:shipping_address], options, true) unless options[:shipping_address].empty?
        add_purchase_data(xml, options[:subscription][:amount], options[:setup_fee], options)
        add_creditcard(xml, options[:credit_card]) if options[:credit_card]
        add_subscription(xml, options)
        add_subscription_update_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_retrieve_subscription_request(identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id
        xml = Builder::XmlMarkup.new :indent => 2
        add_subscription(xml, options)
        add_subscription_retrieve_service(xml, options)
        xml.target!
      end

      def build_subscription_authorization_request(money, identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_subscription(xml, options)
        add_auth_service(xml)
        add_business_rules_data(xml)
        xml.target!
      end

      def build_subscription_purchase_request(money, identification, options)
        reference_code, subscription_id, request_token = identification.split(";")
        options[:subscription] ||= {}
        options[:subscription][:subscription_id] = subscription_id

        xml = Builder::XmlMarkup.new :indent => 2
        add_purchase_data(xml, money, true, options)
        add_subscription(xml, options)
        add_purchase_service(xml, options)
        add_business_rules_data(xml)
        xml.target!
      end

      def add_business_rules_data(xml)
        xml.tag! 'businessRules' do
          xml.tag!('ignoreAVSResult', 'true') if @options[:ignore_avs]
          xml.tag!('ignoreCVResult', 'true') if @options[:ignore_cvv]
        end
      end

      def add_line_item_data(xml, options)
        options[:line_items].each_with_index do |value, index|
          xml.tag! 'item', {'id' => index} do
            xml.tag! 'unitPrice', amount(value[:declared_value])
            xml.tag! 'quantity', value[:quantity]
            xml.tag! 'productCode', value[:code] || 'shipping_only'
            xml.tag! 'productName', value[:description]
            xml.tag! 'productSKU', value[:sku]
          end
        end
      end

      def add_merchant_data(xml, options)
        xml.tag! 'merchantID', @options[:login]
        xml.tag! 'merchantReferenceCode', options[:order_id] || '1111'
        xml.tag! 'clientLibrary' ,'Ruby Active Merchant'
        xml.tag! 'clientLibraryVersion',  '1.0'
        xml.tag! 'clientEnvironment' , 'Linux'
      end

      def add_purchase_data(xml, money = 0, include_grand_total = false, options={})
        xml.tag! 'purchaseTotals' do
          xml.tag! 'currency', options[:currency] || currency(money)
          money == 0 ? xml.tag!('grandTotalAmount','0.0') : xml.tag!('grandTotalAmount', amount(money)) if include_grand_total
        end
      end

      def add_address(xml, address, options, shipTo = false)
        xml.tag! shipTo ? 'shipTo' : 'billTo' do
          xml.tag! 'firstName', address[:first_name]
          xml.tag! 'lastName', address[:last_name]
          xml.tag! 'street1', address[:address1]
          xml.tag! 'street2', address[:address2]
          xml.tag! 'city', address[:city]
          xml.tag! 'state', address[:state]
          xml.tag! 'postalCode', address[:zip]
          xml.tag! 'country', address[:country]
          xml.tag! 'email', options[:email]
        end
      end

      def add_creditcard(xml, creditcard)
        xml.tag! 'card' do
          xml.tag! 'accountNumber', creditcard.number
          xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
          xml.tag! 'expirationYear', format(creditcard.year, :four_digits)
          xml.tag!('cvNumber', creditcard.verification_value) unless (@options[:ignore_cvv] || creditcard.verification_value.blank? )
          xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym]
        end
      end

      def add_tax_service(xml)
        xml.tag! 'taxService', {'run' => 'true'} do
          xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank?
          xml.tag!('sellerRegistration', @options[:vat_reg_number]) unless @options[:vat_reg_number].blank?
        end
      end

      def add_auth_service(xml)
        xml.tag! 'ccAuthService', {'run' => 'true'}
      end

      def add_capture_service(xml, request_id, request_token)
        xml.tag! 'ccCaptureService', {'run' => 'true'} do
          xml.tag! 'authRequestID', request_id
          xml.tag! 'authRequestToken', request_token
        end
      end

      def add_purchase_service(xml, options)
        xml.tag! 'ccAuthService', {'run' => 'true'}
        xml.tag! 'ccCaptureService', {'run' => 'true'}
      end

      def add_void_service(xml, request_id, request_token)
        xml.tag! 'voidService', {'run' => 'true'} do
          xml.tag! 'voidRequestID', request_id
          xml.tag! 'voidRequestToken', request_token
        end
      end

      def add_credit_service(xml, request_id, request_token)
        xml.tag! 'ccCreditService', {'run' => 'true'} do
          xml.tag! 'captureRequestID', request_id
          xml.tag! 'captureRequestToken', request_token
        end
      end

      def add_subscription_create_service(xml, options)
        add_auth_service(xml) if options[:setup_fee]
        xml.tag! 'paySubscriptionCreateService', {'run' => 'true'}
      end

      def add_subscription_update_service(xml, options)
        add_auth_service(xml) if options[:setup_fee]
        xml.tag! 'paySubscriptionUpdateService', {'run' => 'true'}
      end

      def add_subscription_retrieve_service(xml, options)
        xml.tag! 'paySubscriptionRetrieveService', {'run' => 'true'}
      end

      def add_subscription(xml, options)
        xml.tag! 'recurringSubscriptionInfo' do
          xml.tag! 'subscriptionID',    options[:subscription][:subscription_id]
          xml.tag! 'status',            options[:subscription][:status] if options[:subscription][:status]
          xml.tag! 'amount',            options[:subscription][:amount] if options[:subscription][:amount]
          xml.tag! 'numberOfPayments',  options[:subscription][:occurrences] if options[:subscription][:occurrences]
          xml.tag! 'automaticRenew',    options[:subscription][:auto_renew] if options[:subscription][:auto_renew]
          xml.tag! 'frequency',         options[:subscription][:frequency] if options[:subscription][:frequency]
          xml.tag! 'startDate',         options[:subscription][:start_date].strftime("%Y%m%d") if options[:subscription][:start_date]
          xml.tag! 'endDate',           options[:subscription][:end_date].strftime("%Y%m%d")   if options[:subscription][:end_date]
          xml.tag! 'approvalRequired',  options[:subscription][:approval_required] || false
          xml.tag! 'event',             options[:subscription][:event] if options[:subscription][:event]
          xml.tag! 'billPayment',       options[:subscription][:bill_payment] if options[:subscription][:bill_payment]
        end
      end

      # Where we actually build the full SOAP request using builder
      def build_request(body, options)
        xml = Builder::XmlMarkup.new :indent => 2
          xml.instruct!
          xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do
            xml.tag! 's:Header' do
              xml.tag! 'wsse:Security', {'s:mustUnderstand' => '1', 'xmlns:wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'} do
                xml.tag! 'wsse:UsernameToken' do
                  xml.tag! 'wsse:Username', @options[:login]
                  xml.tag! 'wsse:Password', @options[:password], 'Type' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
                end
              end
            end
            xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
              xml.tag! 'requestMessage', {'xmlns' => 'urn:schemas-cybersource-com:transaction-data-1.32'} do
                add_merchant_data(xml, options)
                xml << body
              end
            end
          end
        xml.target!
      end

      # Contact CyberSource, make the SOAP request, and parse the reply into a Response object
      def commit(request, options)
        response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, build_request(request, options)))

        success = response[:decision] == "ACCEPT"
        message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message]
        authorization = success ? [ options[:order_id], response[:requestID], response[:requestToken] ].compact.join(";") : nil

        Response.new(success, message, response,
          :test => test?,
          :authorization => authorization,
          :avs_result => { :code => response[:avsCode] },
          :cvv_result => response[:cvCode]
        )
      end

      # Parse the SOAP response
      # Technique inspired by the Paypal Gateway
      def parse(xml)
        reply = {}
        xml = REXML::Document.new(xml)
        if root = REXML::XPath.first(xml, "//c:replyMessage")
          root.elements.to_a.each do |node|
            case node.name
            when 'c:reasonCode'
              reply[:message] = reply(node.text)
            else
              parse_element(reply, node)
            end
          end
        elsif root = REXML::XPath.first(xml, "//soap:Fault")
          parse_element(reply, root)
          reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
        end
        return reply
      end

      def parse_element(reply, node)
        if node.has_elements?
          node.elements.each{|e| parse_element(reply, e) }
        else
          if node.parent.name =~ /item/
            parent = node.parent.name + (node.parent.attributes["id"] ? "_" + node.parent.attributes["id"] : '')
            reply[(parent + '_' + node.name).to_sym] = node.text
          else
            reply[node.name.to_sym] = node.text
          end
        end
        return reply
      end
    end
  end
end


text:
<?xml version="1.0" encoding="UTF-8"?>
<Addon Author="WintyBadass" APIVersion="15" Name="ForgeUI_ActionBars" Description="">
    <Script Name="ForgeUI_ActionBars.lua"/>
    <Form Name="ForgeUI_ActionBars.xml"/>
    <ReplaceAddon Name="ActionBarFrame"/>
    <ReplaceAddon Name="ActionBarShortcut"/>
    <ReplaceAddon Name="Medic"/>
    <ReplaceAddon Name="PathFrame"/>
    <ReplaceAddon Name="RecallFrame"/>
</Addon>


text:
import weight_responder from './weight-responder';
import measurement_analyzer from './measurement-analyzer';
import http_transmitter from './transmission/http-transmitter';
import weight_transmitter from './transmission/weight-transmitter';
import weight_reader from './weight-reader';

const api = {
  run(filename, target_url) {
    const http_config = {
      target_url: target_url,
      method: 'patch',
    };

    const transmitter = weight_transmitter.create(http_transmitter.create(http_config));
    const analyzer = measurement_analyzer.create();
    const responder = weight_responder.create(transmitter, analyzer);
    const reader = weight_reader.create(filename, responder);
    reader.read();
  },
};

export default api;


text:
/* eslint-disable stdlib/require-globals */

'use strict';

// MODULES //

var tape = require( 'tape' );
var hasSymbolSupport = require( '@stdlib/assert/has-symbol-support' );
var detect = require( './../lib' );

// VARIABLES //

var hasSymbols = hasSymbolSupport();
var hasAsyncIteratorSymbol = ( typeof Symbol === 'function' && typeof Symbol.asyncIterator === 'symbol' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof detect, 'function', 'main export is a function' );
	t.end();
});

tape( 'feature detection result is a boolean', function test( t ) {
	t.strictEqual( typeof detect(), 'boolean', 'detection result is a boolean' );
	t.end();
});

tape( 'if `Symbol.asyncIterator` is supported, detection result is `true`', function test( t ) {
	if ( hasAsyncIteratorSymbol ) {
		t.strictEqual( detect(), true, 'detection result is `true`' );
	} else {
		t.strictEqual( detect(), false, 'detection result is `false`' );
	}
	t.end();
});

tape( 'the function guards against a `Symbol` global variable which does not produce `symbols`', function test( t ) {
	var tmp;
	if ( hasSymbols ) {
		tmp = Symbol;
		Symbol = {}; // eslint-disable-line no-global-assign
	} else {
		global.Symbol = {};
	}
	t.strictEqual( detect(), false, 'detection result is `false`' );
	if ( hasSymbols ) {
		Symbol = tmp; // eslint-disable-line no-global-assign
	}
	t.end();
});


text:
package scala.scalanative.issues

object _260Suite extends tests.Suite {
  test("#260") {
    def getStr(): String = {
      val bytes = Array('h'.toByte, 'o'.toByte, 'l'.toByte, 'a'.toByte)
      new String(bytes)
    }

    val sz = getStr()

    assert("hola" == sz)
    assert("hola".equals(sz))
  }
}


text:
define(function(require) {
    'use strict';

    const $ = require('jquery');
    const _ = require('underscore');
    const BaseView = require('oroui/js/app/views/base/view');
    require('jquery-ui');

    const DraggableSortingView = BaseView.extend({
        /**
         * @inheritDoc
         */
        constructor: function DraggableSortingView(options) {
            DraggableSortingView.__super__.constructor.call(this, options);
        },

        render: function() {
            this.initSortable();
            this.reindexValues();
            return this;
        },

        reindexValues: function() {
            let index = 1;
            this.$('[name$="[_position]"]').each(function() {
                $(this).val(index++);
            });
        },

        initSortable: function() {
            this.$('.sortable-wrapper').sortable({
                tolerance: 'pointer',
                delay: 100,
                containment: 'parent',
                handle: '[data-name="sortable-handle"]',
                stop: _.bind(this.reindexValues, this)
            });
        }
    });

    return DraggableSortingView;
});