text:
import re
import uuid
import urllib
import structlog

from django.conf import settings
from django.http.response import Http404
from django.contrib.messages import warning
from django.utils.deprecation import MiddlewareMixin
from django.middleware.locale import LocaleMiddleware
from django.utils.translation import gettext_lazy as _
from django.http import HttpResponseRedirect
from django.utils.translation import get_language_from_request

from molo.core.utils import get_locale_code
from molo.core.middleware import MoloGoogleAnalyticsMiddleware
from molo.core.models import SiteSettings, ArticlePage, Languages, MoloPage
from molo.core.templatetags.core_tags import load_tags_for_article

from wagtail.core.models import Site

class ForceDefaultLanguageMiddleware(MiddlewareMixin):
    """
    Ignore Accept-Language HTTP headers

    This will force the I18N machinery to always choose settings.LANGUAGE_CODE
    as the default initial language, unless another one is set via sessions or
    cookies

    Should be installed *before* any middleware that
    checks request.META['HTTP_ACCEPT_LANGUAGE'],
    namely django.middleware.locale.LocaleMiddleware
    """
    def process_request(self, request):
        if 'HTTP_ACCEPT_LANGUAGE' in request.META:
            del request.META['HTTP_ACCEPT_LANGUAGE']

class GemLocaleMiddleware(LocaleMiddleware):
    def process_response(self, request, response):
        has_slug = len(request.path.split('/')) > 1
        slug = request.path.split('/')[-1]

        if has_slug and request.path[-1] == '/':
            slug = request.path.split('/')[-2]
        session_exists = request.COOKIES.get('django_language')
        if not session_exists and (has_slug and slug):
            page = MoloPage.objects.filter(slug=slug).first()
            if page:
                specific = getattr(page, 'specific', None)
                specific_language = specific and getattr(
                    page.specific, 'language', None)

                if specific_language:
                    response.set_cookie(
                        'django_language', page.specific.language.locale)

                elif hasattr(page, 'language'):
                    response.set_cookie(
                        'django_language', page.language.locale)
        return response

class LogHeaderInformationMiddleware(MiddlewareMixin):

    def process_request(self, request):
        log = structlog.get_logger()
        log.msg(str(request.META))

class GemMoloGoogleAnalyticsMiddleware(MoloGoogleAnalyticsMiddleware):
    '''
    Submits GA tracking data to a local account or the additional account
    depending on the subdomain in the request

    TODO: Pull the submit_to_local_account and submit_to_global_account
    into the MoloGoogleAnalyticsMiddleware class and override
    submit_to_local_account
    '''

    def load_article_info(self, request):
        """get the tags in an article if the request is for an article page"""
        path = request.get_full_path()
        path_components = [component for component in path.split('/')
                           if component]
        site = Site.find_for_request(request)
        article_info = {}
        try:
            page, args, kwargs = site.root_page.route(
                request,
                path_components)
            if issubclass(type(page.specific), ArticlePage):
                tags_str = ""
                main_lang = Languages.for_site(site).languages.filter(
                    is_main_language=True).first()
                locale_code = get_locale_code(
                    get_language_from_request(request))
                if main_lang.locale == locale_code:
                    article_info['cd5'] = page.specific.title
                else:
                    article_info['cd5'] = page.specific.get_main_language_page(
                    ).title
                qs = load_tags_for_article(
                    {'locale_code': 'en', 'request': request}, page)
                if qs:
                    for q in qs:
                        tags_str += "|" + q.title
                    article_info .update({'cd6': tags_str[1:]})
                    return article_info
        except Http404:
            return article_info
        return article_info

    def get_visitor_id(self, request):
        """Generate a visitor id for this hit.
        If there is a visitor id in the cookie, use that, otherwise
        use the guid if we have one, otherwise use a random number.
        """
        guid = request.META.get('HTTP_X_DCMGUID', '')
        cookie = request.COOKIES.get('__utmmobile')
        if cookie:
            return cookie
        if guid:
            # create the visitor id using the guid.
            cid = guid
        else:
            # otherwise this is a new user, create a new random id.
            cid = str(uuid.uuid4())
        return cid

    def submit_to_local_account(self, request, response, site_settings):
        custom_params = {}

        cd1 = self.get_visitor_id(request)
        custom_params.update({'cd1': cd1})
        if hasattr(request, 'user') and hasattr(request.user, 'profile')\
                and request.user.profile.uuid:
            custom_params.update({'cd2': request.user.profile.uuid})

        if hasattr(request, 'user') and request.user.is_authenticated:
            custom_params.update({'cd3': 'Registered'})
        else:
            custom_params.update({'cd3': 'Visitor'})

        article_info = self.load_article_info(request)
        custom_params.update(article_info)

        local_ga_account = site_settings.local_ga_tracking_code or \
            settings.GOOGLE_ANALYTICS.get('google_analytics_id')
        if local_ga_account:
            return self.submit_tracking(
                local_ga_account,
                request,
                response,
                custom_params)
        return response

    def submit_to_global_account(self, request, response, site_settings):
        custom_params = {}
        cd1 = self.get_visitor_id(request)
        custom_params.update({'cd1': cd1})
        if hasattr(request, 'user') and request.user.is_authenticated:
            custom_params.update({'cd3': 'Registered'})
        else:
            custom_params.update({'cd3': 'Visitor'})

        article_info = self.load_article_info(request)
        custom_params.update(article_info)

        if site_settings.global_ga_tracking_code:
            if hasattr(request, 'user') and hasattr(request.user, 'profile')\
                    and request.user.profile.uuid:
                custom_params.update({'cd2': request.user.profile.uuid})
            return self.submit_tracking(
                site_settings.global_ga_tracking_code,
                request,
                response,
                custom_params)
        return response

    def process_response(self, request, response):
        if hasattr(settings, 'GOOGLE_ANALYTICS_IGNORE_PATH'):
            exclude = [p for p in settings.GOOGLE_ANALYTICS_IGNORE_PATH
                       if request.path.startswith(p)]
            if any(exclude):
                return response
        # Only track 200 and 302 responses for current_site
        if not (response.status_code == 200 or response.status_code == 302):
            return response

        # exclude requests that contain sensitive sensitive information(email)
        if(request.get_full_path().find('/search/?q=') > -1):
            try:
                search_string = urllib.parse.unquote(
                    request.get_full_path().replace('/search/?q=', ''))
            except AttributeError:
                search_string = urllib.unquote(
                    request.get_full_path().replace('/search/?q=', ''))

            if re.match(r'[^@]+@[^@]+\.[^@]+', search_string):
                return response

        site = request._wagtail_site
        site_settings = SiteSettings.for_site(site)
        if site_settings.local_ga_tracking_code or \
                settings.GOOGLE_ANALYTICS.get('google_analytics_id'):
            response = self.submit_to_local_account(
                request, response, site_settings)
        if site_settings.global_ga_tracking_code:
            response = self.submit_to_global_account(
                request, response, site_settings)
        return response

class AdminSiteAdminMiddleware(MiddlewareMixin):

    def process_request(self, request):
        if request.user.is_authenticated:
            is_superuser = request.user.is_superuser
            if not is_superuser and '/admin' in request.path:
                # determine user user.profile.admin_sites
                # perm denied if user is not related to admin_sites
                # redirect to default admin site (first) or home
                site = request._wagtail_site
                if site not in request.user.profile.admin_sites.all():
                    warning(
                        request,
                        _("You do not have the permissions to access {}."
                          .format(site)))
                    site = request.user.profile.admin_sites.first()
                    if site:
                        return HttpResponseRedirect(
                            redirect_to=site.hostname+'/admin/')
                    return HttpResponseRedirect(redirect_to='/')


text:
import {Vec3, Sphere, Box, Plane, ConvexPolyhedron, Trimesh, Heightfield, Shape} from "cannon-es";
import {Object3D, MeshBasicMaterial, SphereBufferGeometry, BoxBufferGeometry, PlaneBufferGeometry, CylinderBufferGeometry, SphereGeometry, BoxGeometry, PlaneGeometry, Mesh, Geometry, Vector3, Face3} from "three";

/**
 * Helper to preview physics objects on the editor.
 *
 * Based on code from CANNON debug shape renderer made by schteppe
 *
 * @class PhysicsObjectHelper
 */
function PhysicsObjectHelper(object, color)
{
	Object3D.call(this);

	/**
	 * Object attached to the helper.
	 *
	 * @attribute object
	 * @type {Object3D}
	 */
	this.object = object;

	/**
	 * Meshes used to represent the shapes attached to the body.
	 *
	 * @attribute meshes
	 * @type {Array}
	 */
	this.meshes = [];
	this.matrixAutoUpdate = false;

	this.material = new MeshBasicMaterial(
		{
			color: color !== undefined ? color : 0x00FF00,
			wireframe: false,
			transparent: true,
			opacity: 0.5
		});
}

PhysicsObjectHelper.SPHERE = new SphereBufferGeometry(1, 32, 32);
PhysicsObjectHelper.BOX = new BoxBufferGeometry(1, 1, 1);
PhysicsObjectHelper.PLANE = new PlaneBufferGeometry(100, 100);
PhysicsObjectHelper.CYLINDER = new CylinderBufferGeometry(1, 1, 10, 32);

PhysicsObjectHelper.prototype = Object.create(Object3D.prototype);

/**
 * Update the helper from the physics body.
 *
 * @method update
 */
PhysicsObjectHelper.prototype.update = function()
{
	this.matrix.copy(this.object.matrixWorld);

	var body = this.object.body;
	var index = 0;

	// Iterate all the shapes in the physics body
	for (var j = 0; j < body.shapes.length; j++)
	{
		var shape = body.shapes[j];

		this.updateMesh(index, body, shape);

		var mesh = this.meshes[index];
		if (mesh !== undefined)
		{
			var tmpVec = new Vec3();
			var tmpQuat = new Vec3();

			// Get world position
			body.quaternion.vmult(body.shapeOffsets[j], tmpVec);
			body.position.vadd(tmpVec, tmpVec);

			// Get world quaternion
			body.quaternion.mult(body.shapeOrientations[j], tmpQuat);

			// Copy to meshes
			mesh.position.copy(tmpVec);
			mesh.quaternion.copy(tmpQuat);
		}

		index++;
	}

	for (var i = index; i < this.meshes.length; i++)
	{
		var mesh = index[i];
		if (mesh)
		{
			this.remove(mesh);
		}
	}

	this.meshes.length = index;
};

PhysicsObjectHelper.prototype.updateMesh = function(index, body, shape)
{
	var mesh = this.meshes[index];
	if (!this.typeMatch(mesh, shape))
	{
		if (mesh)
		{
			this.remove(mesh);
		}
		mesh = this.meshes[index] = this.createMesh(shape);
	}

	this.scaleMesh(mesh, shape);
};

/**
 * Check if the mesh attahched to this helper object matches the CANNON body shape.
 *
 * @method typeMatch
 * @return {boolean} True if the mesh matches the shape.
 */
PhysicsObjectHelper.prototype.typeMatch = function(mesh, shape)
{
	if (!mesh)
	{
		return false;
	}

	var geometry = mesh.geometry;

	return geometry instanceof SphereGeometry && shape instanceof Sphere ||
	geometry instanceof BoxGeometry && shape instanceof Box ||
	geometry instanceof PlaneGeometry && shape instanceof Plane ||
	(geometry.id === shape.geometryId && (shape instanceof ConvexPolyhedron || shape instanceof Trimesh) || shape instanceof Heightfield);
};

/**
 * Create a mesh to represent a CANNON physics shape and attach it to this helper object.
 *
 * @method createMesh
 * @return {Mesh} Mesh created to represent the shape.
 */
PhysicsObjectHelper.prototype.createMesh = function(shape)
{
	var material = this.material;
	var mesh = null;

	switch (shape.type)
	{
	case Shape.types.SPHERE:
		mesh = new Mesh(PhysicsObjectHelper.SPHERE, material);
		break;

	case Shape.types.PARTICLE:
		mesh = new Mesh(PhysicsObjectHelper.SPHERE, material);
		break;

	case Shape.types.BOX:
		mesh = new Mesh(PhysicsObjectHelper.BOX, material);
		break;

	case Shape.types.PLANE:
		mesh = new Mesh(PhysicsObjectHelper.PLANE, material);
		mesh.scale.set(1000, 1000, 1);
		break;

	case Shape.types.CONVEXPOLYHEDRON:
		// Create mesh
		var geo = new Geometry();

		// Add vertices
		for (var i = 0; i < shape.vertices.length; i++)
		{
			var v = shape.vertices[i];
			geo.vertices.push(new Vector3(v.x, v.y, v.z));
		}

		// Add faces
		for (var i = 0; i < shape.faces.length; i++)
		{
			var face = shape.faces[i];

			// Add triangles
			var a = face[0];
			for (var j = 1; j < face.length - 1; j++)
			{
				var b = face[j];
				var c = face[j + 1];
				geo.faces.push(new Face3(a, b, c));
			}
		}
		geo.computeBoundingSphere();
		geo.computeFaceNormals();
		mesh = new Mesh(geo, material);
		shape.geometryId = geo.id;
		break;

	case Shape.types.TRIMESH:
		var geometry = new Geometry();
		var v0 = new Vec3();
		var v1 = new Vec3();
		var v2 = new Vec3();
		for (var i = 0; i < shape.indices.length / 3; i++)
		{
			shape.getTriangleVertices(i, v0, v1, v2);
			geometry.vertices.push(new Vector3(v0.x, v0.y, v0.z), new Vector3(v1.x, v1.y, v1.z), new Vector3(v2.x, v2.y, v2.z));
			var j = geometry.vertices.length - 3;
			geometry.faces.push(new Face3(j, j+1, j+2));
		}
		geometry.computeBoundingSphere();
		geometry.computeFaceNormals();
		mesh = new Mesh(geometry, material);
		shape.geometryId = geometry.id;
		break;

	case Shape.types.HEIGHTFIELD:
		var geometry = new Geometry();
		var v0 = new Vec3();
		var v1 = new Vec3();
		var v2 = new Vec3();

		for (var xi = 0; xi < shape.data.length - 1; xi++)
		{
			for (var yi = 0; yi < shape.data[xi].length - 1; yi++)
			{
				for (var k = 0; k < 2; k++)
				{
					shape.getConvexTrianglePillar(xi, yi, k === 0);
					v0.copy(shape.pillarConvex.vertices[0]);
					v1.copy(shape.pillarConvex.vertices[1]);
					v2.copy(shape.pillarConvex.vertices[2]);
					v0.vadd(shape.pillarOffset, v0);
					v1.vadd(shape.pillarOffset, v1);
					v2.vadd(shape.pillarOffset, v2);
					geometry.vertices.push(new Vector3(v0.x, v0.y, v0.z), new Vector3(v1.x, v1.y, v1.z), new Vector3(v2.x, v2.y, v2.z));
					var i = geometry.vertices.length - 3;
					geometry.faces.push(new Face3(i, i + 1, i + 2));
				}
			}
		}

		geometry.computeBoundingSphere();
		geometry.computeFaceNormals();
		mesh = new Mesh(geometry, material);
		shape.geometryId = geometry.id;
		break;
	}

	if (mesh !== null)
	{
		this.add(mesh);
	}

	return mesh;
};

/**
 * Set to correct scale of the helper mesh based on the shape type and size configuration.
 *
 * @method scaleMesh
 * @param {Mesh} mesh Mesh to be changed.
 * @param {Shape} shape Shape to analyse and extract scale from.
 */
PhysicsObjectHelper.prototype.scaleMesh = function(mesh, shape)
{
	var type = shape.type;

	if (type === Shape.types.SPHERE)
	{
		var radius = shape.radius;
		mesh.scale.set(radius, radius, radius);
	}
	else if (type === Shape.types.PARTICLE)
	{
		mesh.scale.set(0.1, 0.1, 0.1);
	}
	else if (type === Shape.types.BOX)
	{
		mesh.scale.copy(shape.halfExtents);
		mesh.scale.multiplyScalar(2);
	}
	else if (type === Shape.types.CONVEXPOLYHEDRON)
	{
		mesh.scale.set(1, 1, 1);
	}
	else if (type === Shape.types.TRIMESH)
	{
		mesh.scale.copy(shape.scale);
	}
	else if (type === Shape.types.HEIGHTFIELD)
	{
		mesh.scale.set(1, 1, 1);
	}
};

export {PhysicsObjectHelper};

redpajama_set_name: RedPajamaGithub


text:
All tests on squbs have been written using ScalaTest 2.x. Specs2 has not yet been tested.

##Dependencies

To use test utilities mentioned in this documentation,, simply add the following dependencies in your `build.sbt` file or Scala build script:

```
"org.squbs" %% "squbs-testkit" % squbsVersion
```

##CustomTestKit

The `CustomTestKit` is used for starting a full blown squbs instance needed for testing bits and pieces of applications.  `CustomTestKit` is simple to use and needs no configuration by default, yet allows customizations and flexibility for your tests.  With `CustomTestKit` you can start any number of `ActorSystem` and `Unicomplex` instances (one per `ActorSystem`) with different configurations - all on the same JVM.  Here are some features:

   * It automatically sets actor system name to spec/test class name for simplicity and also to ensure `ActorSystem` instances do not conflict.  But, it also allows actor system name to be passed in the constructor.
   * Tests extending `CustomTestKit` can run in parallel in the same JVM.
   * Starts and stops squbs automatically.
   * Starts well-known actors and service in `src/main/resources/META-INF/squbs-meta.conf` and `src/test/resources/META-INF/squbs-meta.conf` by default.  But, allows passing `resources` to be scanned in the constructor.
   * Allows custom configuration to be passed in the constructor.

Here is an example usage of `CustomTestKit` in ScalaTest:

```scala
class SampleSpec extends CustomTestKit with FlatSpecLike with Matchers {
   it should "start the system" in {
      system.startTime should be > 0L
   }
}
```

Both TestNG and JUnit are supported for Java users:

```java
public class SampleTest extends AbstractCustomTestKit {

    @Test
    public void testSystemStartTime() {
        Assert.assertTrue(system().startTime() > 0L);
    }
}
```

###Passing configuration to `CustomTestKit`

If you would like to customize the actor system configuration, you can pass a `Config` object to `CustomTestKit`:

```scala
object SampleSpec {
  val config = ConfigFactory.parseString {
      """
        |akka {
        |  loglevel = "DEBUG"
        |}
      """.stripMargin
  }
}

class SampleSpec extends CustomTestKit(SampleSpec.config) with FlatSpecLike with Matchers {

  it should "set akka log level to the value defined in config" in {
    system.settings.config.getString("akka.loglevel") shouldEqual "DEBUG"
  }
}
```

Here is the TestNG/JUnit version of this test:

```java
public class SampleTest extends AbstractCustomTestKit {

    public SampleTest() {
        super(TestConfig.config);
    }

    @Test
    public void testAkkaLogLevel() {
        Assert.assertEquals(system().settings().config().getString("akka.loglevel"), "DEBUG");
    }

    private static class TestConfig {
        private static Config config = ConfigFactory.parseString("akka.loglevel = DEBUG");
    }
}
```

The following sections show customizations only in ScalaTest; however, all these customizations are supported for TestNG and JUnit as well.  For customizations, provide a `public` constructor in your TestNG/JUnit tests and call `super` with custom parameters.  Check [squbs-testkit/src/test/java/org/squbs/testkit/japi](../squbs-testkit/src/test/java/org/squbs/testkit/japi) for more TestNG and JUnit samples.

Specifically for JUnit, avoid setting actor system name in your tests (letting `CustomTestKit` set the actor system name is in general a good practice though).  JUnit creates a new fixture instance for each `@Test` method which potentially causes actor system conflicts.  `AbstractCustomTestKit` avoids this by appending an incremented integer to each actor system name.

###Starting well-known actors and services with `CustomTestKit`

`CustomTestKit` will automatically start well-known actors and services in `src/test/resources/META-INF/squbs-meta.conf` (see [Bootstrapping squbs](bootstrap.md#well-known-actors)).  However, if you would like provide different resource paths, you can do so by passing a `Seq` of resources to the constructor.  `withClassPath` controls whether to scan entire test classpath for `META-INF/squbs-meta.conf` files or not.

```scala
object SampleSpec {
	val resources = Seq(getClass.getClassLoader.getResource("").getPath + "/SampleSpec/META-INF/squbs-meta.conf")
}

class SampleSpec extends CustomTestKit(SampleSpec.resources, withClassPath = false)
  with FlatSpecLike with Matchers {

  // Write tests here
}
```

Please note, `CustomTestKit` allows passing `config` and `resources` together as well.

####Port binding in tests

Starting services requires port binding.  To prevent port conflicts, we should let the system pick a port by setting listeners' `bind-port` to 0, e.g., `default-listener.bind-port = 0` (this is what `CustomTestKit` sets by default).  `squbs-testkit` comes with a `trait` named `PortGetter` that allows retrieving the port picked by the system.  `CustomTestKit` comes with `PortGetter` already mixed in, so you can use `port` value.

```scala
class SampleSpec extends CustomTestKit(SampleSpec.resources)

  "PortGetter" should "retrieve the port" in {
    port should be > 0
  }
}

```

By default, `PortGetter` returns `default-listener`'s port, which is the most common one.  If you need to retrieve another listener's bind port, you can either override `listener` method or pass listener name to `port` method:

```scala
class SampleSpec extends CustomTestKit(SampleSpec.resources)

  override def listener = "my-listener"

  "PortGetter" should "return the specified listener's port" in {
    port should not equal port("default-listener")
    port shouldEqual port("my-listener")
  }
}
```

###Manual `UnicomplexBoot` initialization

`CustomTestKit` allows a `UnicomplexBoot` instance to be passed as well.  This allows full customization of the bootrap.  Please see [Bootstrapping squbs](bootstrap.md) for more information on booting the Unicomplex.

```scala
object SampleSpec {
  val config = ConfigFactory.parseString(
    s"""
       |squbs {
       |  actorsystem-name = SampleSpec # should be unique to prevent collision with other tests running in parallel
       |  ${JMX.prefixConfig} = true # to prevent JMX name collision, if you are doing any JMX testing
       |}
    """.stripMargin
  )

  val resource = getClass.getClassLoader.getResource("").getPath + "/SampleSpec/META-INF/squbs-meta.conf"

  val boot = UnicomplexBoot(config)
    .createUsing {(name, config) => ActorSystem(name, config)}
    .scanResources(resource)
    .initExtensions.start()
}

class SampleSpec extends CustomTestKit(SampleSpec.boot) with FunSpecLike with Matchers {

  // Write your tests here.
}
```

##Testing Spray/Akka Http Routes using Spray/Akka Http TestKit

The `spray-testkit` or `akka-http-testkit` needs to be added to the dependencies in order to test routes.  Please add the followings to your dependencies:

For Spray:

```
"io.spray" %% "spray-testkit" % sprayV % "test"
```

For Akka-Http:

```
"com.typesafe.akka" %% "akka-http-testkit" % akkaV % "test"
```

### Usage
As you specify routes in squbs by extending the `RouteDefinition` trait which squbs will compose with actors behind
the scenes, it can be difficult to construct routes for use with the Spray/Akka Http TestKit test DSL. `TestRoute` is provided
for constructing and obtaining routes from the `RouteDefinition`. To use it, just pass the `RouteDefinition` as a type
parameter to `TestRoute`. This will obtain you a fully configured and functional route for the test DSL as can be seen
in the example below.

Specifying the `RouteDefinition`

```scala
package com.myorg.mypkg

import org.squbs.unicomplex.RouteDefinition
import spray.routing.Directives._

class MyRoute extends RouteDefinition {

  val route =
    path("ping") {
      get {
        complete {
          "pong"
        }
      }
    }
}
```

Implementing the test, obtaining route from `TestRoute[MyRoute]`:

```scala
package com.myorg.mypkg

import org.scalatest.{Matchers, FlatSpecLike}
import org.squbs.testkit.TestRoute
import spray.testkit.ScalatestRouteTest

class MyRouteTest extends FlatSpecLike with Matchers with ScalatestRouteTest {

  val route = TestRoute[MyRoute]

  it should "return pong on a ping" in {
    Get("/ping") ~> route ~> check {
      responseAs[String] should be ("pong")
    }
  }
}
```

Alternatively, you may also want to pass a web context to your route. This can be done by passing it to `TestRoute` as follows:

```scala
  val route = TestRoute[MyRoute](webContext = "mycontext")
```

or just pass `"mycontext"` without the parameter name. The `TestRoute` signature without parameters is equivalent to passing the root context `""`.

###Using TestRoute with CustomTestKit

A need may arise to bootstrap `Unicomplex` while testing with `TestRoute`, such as when:

   * a squbs well-known actor is involved in request handling.
   * [The Actor Registry](registry) is used during request handling.

Using Akka's `TestKit` together with `ScalatestRouteTest` can be tricky as they have conflicting initialization.  squbs provides a test utility named `CustomRouteTestKit` to solve this problem.  `CustomRouteTestKit` supports all the APIs provided by `CustomTestKit`.  Here is an example usage of `TestRoute` with `CustomRouteTestKit`:

```scala
class MyRouteTest extends CustomRouteTestKit with FlatSpecLike with Matchers {

  it should "return response from well-known actor" in {
    val route = TestRoute[ReverserRoute]
    Get("/msg/hello") ~> route ~> check {
      responseAs[String] should be ("hello".reverse)
    }
  }
}

class ReverserRoute extends RouteDefinition {
  import akka.pattern.ask
  import Timeouts._
  import context.dispatcher

  val route =
    path("msg" / Segment) { msg =>
      get {
        onComplete((context.actorSelection("/user/mycube/reverser") ? msg).mapTo[String]) {
          case Success(value) => complete(value)
          case Failure(ex)    => complete(s"An error occurred: ${ex.getMessage}")
        }
      }
    }
}
```

**Note:** To use `CustomRouteTestKit`, please ensure the Spray or Akka Http testkit is in your dependencies as described [above](#testing-sprayakka-http-routes-using-sprayakka-http-testkit).


text:
layout: post
title: "ISL: Resampling Methods"
description: ""
category: Machine-Learning
tags: [Bootstrap]
---
{% include JB/setup %}

总结自 Chapter 5, An Introduction to Statistical Learning.

-----

ToC:

- [0. Overview](#0-overview)
- [1. Cross-Validation](#1-cross-validation)
	- [1.1 The Validation Set Approach](#11-the-validation-set-approach)
	- [1.2 Leave-One-Out Cross-Validation](#12-leave-one-out-cross-validation)
	- [1.3 k-Fold Cross-Validation](#13-k-fold-cross-validation)
	- [1.4 Bias-Variance Trade-Off for k-Fold Cross-Validation](#14-bias-variance-trade-off-for-k-fold-cross-validation)
	- [1.5 Cross-Validation on Classification Problems](#15-cross-validation-on-classification-problems)
- [2. The Bootstrap](#2-the-bootstrap)
- [3. Lab: Cross-Validation and the Bootstrap](#3-lab-cross-validation-and-the-bootstrap)
	- [3.1 The Validation Set Approach](#31-the-validation-set-approach)
	- [3.2 Leave-One-Out Cross-Validation](#32-leave-one-out-cross-validation)
	- [3.3 k-Fold Cross-Validation](#33-k-fold-cross-validation)
	- [3.4 The Bootstrap](#34-the-bootstrap)
		- [3.4.1 Estimating the Accuracy of a Statistic of Interest](#341-estimating-the-accuracy-of-a-statistic-of-interest)
		- [3.4.2 Estimating the Accuracy of a Linear Regression Model](#342-estimating-the-accuracy-of-a-linear-regression-model)

-----

## 0. Overview

Resampling methods involve:

* repeatedly drawing samples from a training set
* refitting a model of interest on each sample in order to obtain additional information about the fitted model

In this chapter, we discuss two of the most commonly
used resampling methods:

* cross-validation, which can be used for
	* **model assessment**, the process of evaluating a model's performance
	* **model selection**, the process of selecting the proper level of flexibility for a model
* bootstrap, which is used most commonly to provide a measure of accuracy of a parameter estimate or of a given statistical learning method.

## 1. Cross-Validation

注意我们的目的是 estimate the test error rate,因为真实的 test error rate 是不可测量的。

### 1.1 The Validation Set Approach

The validation set approach involves randomly dividing the available set of observations into two parts, a **training set** and a **validation set** (a.k.a. hold-out set).

* The model is fit on the training set.
* The fitted model is used to predict the responses for the observations in the validation set.
	* The resulting validation set error rate — typically assessed using MSE in the case of a quantitative response — provides an estimate of the test error rate.

The validation set approach is conceptually simple and is easy to implement. But it has two potential drawbacks:

* The validation estimate of the test error rate can be highly variable, depending on precisely which observations are included in the training set and which observations are included in the validation set.
* Only a subset of the observations — those that are included in the training set — are used to fit the model. Since statistical methods tend to perform worse when trained on fewer observations, this suggests that the validation set error rate may tend to **overestimate** the test error rate for the model fit on the entire data set.

Cross-validation is a refinement of the validation set approach that addresses these two issues.

简单来说:

- Validation Set Approach: 只有一次分割 Training / Validation 的操作
	- 所以也只有一个 estimate on validation set
- Cross Validation: 有多次分割 Training / Validation 的操作
	- 所以可以在多个 validation set 上 estimate 再求平均
- validation set == hold-out set

### 1.2 Leave-One-Out Cross-Validation

P178

简单说就是每次只留一个 $(x_i, y_i)$ 作为 validation set,其余的 $n-1$ 个作为 training set。比如第一次留 $(x_1, y_1)$,得到 $model_1$,计算得 $MSE_1$。如此 repeat $n$ 次。

The LOOCV estimate for the test MSE is the average of these $n$ test error estimates:

$$
\begin{equation}
	CV_{(n)} = \frac{1}{n} \sum_{i=1}^{n}{MSE_i} = \frac{1}{n} \sum_{i=1}^{n}{(y_i - \hat{y}_i)^2}
	\tag{1.1}
\end{equation}
$$

LOOCV's advantages over the validation set approach:

* far less bias because of larger size of training set
	* Consequently, the LOOCV approach tends not to overestimate the test error rate as much as the validation set approach does
* when applied repeatedly
	* due to randomness in the training/validation set splits, validation set approach may yields quite different results.
	* LOOCV's always yields the same results.

LOOCV can be very time consuming if $n$ is large, and if
each individual model is slow to fit. With least squares linear or polynomial regression, there is an amazing shortcut to compute $CV_{(n)}$ with only one model fit, as

$$
\begin{equation}
	CV_{(n)} = \frac{1}{n} \sum_{i=1}^{n}{\left ( \frac{y_i - \hat{y}_i}{1 - h_i} \right )^2 }
	\tag{1.2}
	\label{eq1.2}
\end{equation}
$$

where $h_i$ is the [leverage-statistic](http://erikyao.github.io/machine-learning/2014/09/21/machine-learning-linear-regression-part-2#High-Leverage-Points). The leverage lies between $\frac{1}{n}$ and 1, and reflects the amount that an observation influences its own fit. Hence the residuals for high-leverage points are inflated (inflate = enlarge) in this formula.

### 1.3 k-Fold Cross-Validation

This approach involves randomly dividing the set of observations into $k$ groups, or folds, of approximately equal size. On the $i^{th}$ loop, keep the $i^{th}$ fold as a validation set, and the model is fit on the remaining $k-1$ folds. Repeat this procedure $k$ times.

The $k$-fold CV estimate is computed by averaging these values,

$$
\begin{equation}
	CV_{(k)} = \frac{1}{k} \sum_{i=1}^{k}{MSE_i} = \frac{1}{k} \sum_{i=1}^{k}{(y_i - \hat{y}_i)^2}
	\tag{1.3}
\end{equation}
$$

It is not hard to see that LOOCV is a special case of $k$-fold CV in which $k$ is set to equal $n$. In practice, one typically performs $k$-fold CV using $k = 5$ or $k = 10$.

The most obvious advantage over LOOCV is computational.

### 1.4 Bias-Variance Trade-Off for k-Fold Cross-Validation

On bias:

* LOOCV 的 training set 的比例最大,所以 LOOCV will give approximately unbiased estimates of the test error
* k-fold ($k < n$)的 bias 略高
* Validation Set Approach 自然是 bias 最高

On variance: It turns out that LOOCV has higher variance than does k-fold CV with $k < n$. Why?

* When we perform LOOCV, we are in effect averaging the outputs of $n$ fitted models, each of which is trained on an almost identical set of observations; therefore, these outputs are highly (positively) correlated with each other.
* In contrast, when we perform k-fold CV with $k < n$, we are averaging the outputs of $k$ fitted models that are somewhat less correlated with each other, since the overlap between the training sets in each model is smaller.
*  Since the mean of many highly correlated quantities has higher variance, the test error estimate resulting from LOOCV tends to have higher variance than the one from $k$-fold CV.

$k = 5$ or $k = 10$ been shown empirically to yield test error rate estimates that suffer neither from excessively high bias nor from very high variance.

### 1.5 Cross-Validation on Classification Problems

Cross-validation works the same way on classification problems, except that rather than using MSE, we instead use the number of misclassified observations, i.e. error rate to quantify test error.

$$
\begin{equation}
	CV_{(n)} = \frac{1}{n} \sum_{i=1}^{n}{Err_i}
	\tag{1.4}
\end{equation}
$$

P185-186 是一个借助 CV 来选择 Order of Polynomials 的例子,其实挺简单的,用 $k = 5$ or $k = 10$ 来 estimate 不同 order 的 Polynomial model 的 test error rate,选最小的 test error rate estimate 对应的 order 即可。

## 2. The Bootstrap

先解释下 bootstrap 这个词是啥意思吧,用了这么久的 jekyll bootstrap 也没认真查过……

首先 strap 是 a narrow and usually flat piece of a material that is used for fastening, holding together, or wrapping something。

然后 [bootstrap 的意思](https://en.wiktionary.org/wiki/strap) 有:

1. A strap sewn at the side or top rear of a boot to help in pulling the boot on.
	![](https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Dr_Martens%2C_black%2C_old.jpg/220px-Dr_Martens%2C_black%2C_old.jpg "The bootstrap can be seen at the top of the boot that is standing upright.")
2. A means of advancing oneself or accomplishing something without aid, as in "He used his business experience as a bootstrap to win voters".
3. (computing) The process by which the operating system of a computer is loaded into its memory
4. (computing) The process necessary to compile the tools that will be used to compile the rest of the system or program.
5. (statistics) Any method or instance of estimating properties of an estimator (such as its variance) by measuring those properties when sampling from an approximating distribution.

Clear now? Ok, let's get started!

P187

The bootstrap is a statistical tool to quantify the uncertainty associated with a given estimator or statistical learning method.

在实验时,我们常用的一种手段是:

1. 自己制定一个或者多个 parameter,比如 $\mu=0$
2. 按 parameter 来 generate samples
3. 在这些 sample 上做 estimate,看是否接近 parameter

但是 for real data we cannot generate new samples from the original population,这时就可以用 bootstrap 了。

The bootstrap approach allows us to emulate the process of obtaining new sample sets, so that we can estimate without generating additional samples.

P189 阐述了 bootstrap 的做法,其实挺简单:

1. 假设原 data set 有 $n$ 个 observation
2. Randomly select $n$ observations from the data set to produce a bootstrap data set. This sampling is performed **with replacement**, which means that the same observation can occur more than once in the bootstrap data set.
3. 假设生成了 $B$ 个 bootstrap data set,我们就在这 $B$ 个 bootstrap data set 上做 estimate

~~~~~ 2016.08.16 补充 start ~~~~~

其实我觉得 [wikipedia: Bootstrap aggregating](https://en.wikipedia.org/wiki/Bootstrap_aggregating) 的解释更清楚一点:

> Given a standard **training set** $D$ of size $n$, bagging generates $m$ new training sets $D_1,D_2,\dots,D_m$, each of size $n'$, by sampling from D uniformly and **with replacement**. By sampling with replacement, some observations may be repeated in each $D_i$. If $n'=n$, then for large $n$, the set $D_i$ is expected to have the fraction $1 - \frac{1}{e} \approx 63.2\%$ of the unique examples of $D$, the rest being duplicates. This kind of sample is known as a **bootstrap sample**. The $m$ models are fitted using the above $m$ bootstrap samples and combined by averaging the output (for regression) or voting (for classification).

~~~~~ 2016.08.16 补充 end ~~~~~

## 3. Lab: Cross-Validation and the Bootstrap

### 3.1 The Validation Set Approach

```r
> library(ISLR)
> set.seed(1)
> train = sample(392,196) ## 从 [1,392] 中选择 196 个整数

> lm.fit = lm(mpg~horsepower, data=Auto, subset=train)
> mean((Auto$mpg - predict(lm.fit, Auto))[-train]^2) ## MSE
```

### 3.2 Leave-One-Out Cross-Validation

The LOOCV estimate can be automatically computed for any generalized linear model using the `glm()` and `cv.glm()` functions together.

In previous lab, we used the `glm()` function to perform logistic regression by passing in the `family="binomial"` argument. If we don't pass this `family` argument, then it performs linear regression, just like the lm() function. Then the result can be passed to `cv.glm()` to perform the LOOCV estimate.

The `cv.glm()` function is part of the `boot` library.

```r
> library(boot)
> glm.fit = glm(mpg~horsepower, data=Auto)
> cv.err = cv.glm(Auto, glm.fit)
> cv.err$delta
1 1
24.23 24.23
```

这里注意下 `delta`。`cv.glm` 本身是为 $k$-fold 设计的,如果不传一个 $k$ 值的话,默认就是 LOOCV。`cv.glm` 其实计算了两个 MSE,都放在 `delta` 里传回来了:

* The first component is the raw cross-validation estimate of prediction error.
* The second component is the adjusted cross-validation estimate. The adjustment is designed to compensate for the bias introduced by not using leave-one-out cross-validation.

所以这个 adjusted cross-validation estimate 是仅当用 $k$-fold 时才有点意义,在用 LOOCV 时,这两个值是基本 identical 的。而且目前我们也只用第一个值就够了。

### 3.3 k-Fold Cross-Validation

```r
> set.seed(17)
> cv.error.10 = rep(0,10)
> for (i in 1:10) {
+ 	glm.fit=glm(mpg~poly(horsepower,i), data=Auto)
+ 	cv.error.10[i]=cv.glm(Auto, glm.fit, K=10)$delta [1]
+ }
> cv.error.10
[1] 24.21 19.19 19.31 19.34 18.88 19.02 18.90 19.71 18.95 19.50
```

In principle, the computation time for LOOCV for a least squares linear model should be faster than for $k$-fold CV, due to the availability of the formula $(\ref{eq1.2})$ for LOOCV; however, unfortunately the `cv.glm()` function does not make use of this formula.

### 3.4 The Bootstrap

#### 3.4.1 Estimating the Accuracy of a Statistic of Interest

Performing a bootstrap analysis in R entails only two steps.

* First, we must create a function that computes the statistic of interest.
* Second, we use the `boot()` function, which is part of the `boot` library, to perform the bootstrap.

We use the `Portfolio` data set in the `ISLR` package here.

we first create a function, `alpha.fn()`, which takes as input the $(X, Y)$ data as well as a vector indicating which observations should be used to estimate $\alpha$. The function then return the estimate for $\alpha$ based on the selected observations.

```r
> alpha.fn = function(data, index){
+ 	X=data$X[index]
+ 	Y=data$Y[index]
+ 	return ((var(Y)-cov(X,Y)) / (var(X)+var(Y)-2*cov(X,Y)))
+ }
```

在用 `boot()` 之前,我们可以自己先手动模拟一下:

```r
> set.seed(1)
> alpha.fn(Portfolio, sample(100,100,replace=T)) ## nrow(Portfolio) = 100
[1] 0.596
```

We can implement a bootstrap analysis by performing this command many times, recording all of the corresponding estimates for $\alpha$, and computing the resulting standard deviation. However, the `boot()` function automates this approach.

```r
> boot(Portfolio, alpha.fn, R=1000) # R = 1000 is the number of bootstrap replicates, i.e. the B number mentioned in Section 2

ORDINARY NONPARAMETRIC BOOTSTRAP

Call:
boot(data = Portfolio, statistic = alpha.fn, R = 1000)

Bootstrap Statistics :
original     bias  std . error
t1*   0.5758  -7.315e   -05 0.0886
```

#### 3.4.2 Estimating the Accuracy of a Linear Regression Model

P195 没啥新内容

P196 论述了 CV 没有依赖某些假设,所以得到 estimate 比那些依赖假设的公式其实要来的准。

注意下 `xxx.fn` 这个函数可以 return 多个值,比如 `return (coef(lm(mpg~horsepower, data=data, subset=index)))` 这样。我们知道 `coef()` 是 return 了 slope 和 intercept 两个值,这样 `boot()` 的结果里 Bootstrap Statistics 就有 `t1*`、`t2*` 两行,依此类推。


text:
package com.bazoud.elasticsearch.river.git.flow;

import org.eclipse.jgit.revwalk.RevWalk;

import com.bazoud.elasticsearch.river.git.beans.Context;
import com.bazoud.elasticsearch.river.git.flow.functions.TagToIndexTag;
import com.bazoud.elasticsearch.river.git.flow.visitors.BulkVisitor;
import com.bazoud.elasticsearch.river.git.guava.MyFunction;
import com.bazoud.elasticsearch.river.git.guava.Visitors;
import com.google.common.collect.FluentIterable;

import static com.bazoud.elasticsearch.river.git.IndexedDocumentType.TAG;

/**
 * @author Olivier Bazoud
 */
public class TagIndexFunction extends MyFunction<Context, Context> {

    @Override
    public Context doApply(Context context) throws Throwable {
        RevWalk walk = new RevWalk(context.getRepository());

        Visitors.visit(
            FluentIterable
                .from(context.getRepository().getTags().entrySet())
                .transform(new TagToIndexTag(context, walk)),
            new BulkVisitor(context, TAG.name().toLowerCase())
        );

        return context;
    }

}


text:
package bingo.odata.consumer.test;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

import bingo.odata.consumer.ODataConsumerImplTest;
import bingo.odata.consumer.requests.behaviors.BehaviorTest;

@RunWith(Suite.class)
@SuiteClasses({ODataConsumerImplTest.class, BehaviorTest.class})
public class TestAll extends TestWithServerRunning{

}


text:
package org.vitrivr.cineast.core.data.m3d;

import java.awt.Color;

import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector3i;
import org.joml.Vector4i;

/**
 * @author rgasser
 * @version 1.0
 * @created 15.03.17
 */
public interface WritableMesh extends ReadableMesh {
    /**
     * Adds a new triangular face to the Mesh. Faces index vertices and
     * vertex normals.
     *
     * @param vertices Vector3i containing the indices of the vertices.
     * @return true if face could be added and false otherwise (e.g. if indices point to non-existing vertex)
     */
    boolean addFace(Vector3i vertices);

    /**
     * Adds a new quadratic face to the Mesh. Faces index vertices and
     * vertex normals.
     *
     * @param vertices Vector4i containing the indices of the vertices.
     * @return true if face could be added and false otherwise (e.g. if indices point to non-existing vertex)
     */
    boolean addFace(Vector4i vertices);

    /**
     * Scales the Mesh by the provided factor. This will reset the surfaceArea and bounding-box property.
     *
     * @param factor Factor by which the Mesh should be scaled. Values < 1.0 will cause the Mesh to shrink.
     */
    void scale(float factor);

    /**
     * Moves the Mesh in the direction of the provided vector.
     *
     * @param translation Vector describing the translation in the three directions.
     */
    void move(Vector3f translation);

    /**
     * Applies a transformation matrix on the Mesh by applying it to all its vertices.
     *
     * @param transformation Transformation matrix that should be applied.
     */
   void transform(Matrix4f transformation);

    /**
     * Updates the color of a vertex.
     *
     * @param vertexIndex Index of the vertex that should be upadated.
     * @param color New color of the vertex.
     */
    void updateColor(int vertexIndex, Color color);
}


text:
#include <pthread.h>
#include <sys/utsname.h>

unsigned long pthread_self()
{
    return (unsigned long) GetCurrentThreadId();
}

int pthread_mutex_init(pthread_mutex_t *mutex, void *v)
{
    (void) v;

    InitializeCriticalSection(&(mutex->criticalSection));

    return 0;
}

int pthread_mutex_lock(pthread_mutex_t *mutex)
{
    EnterCriticalSection(&(mutex->criticalSection));

    return 0;
}

int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
    LeaveCriticalSection(&(mutex->criticalSection));

    return 0;
}

int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
    DeleteCriticalSection(&(mutex->criticalSection));

    return 0;
}

int uname(struct utsname *u)
{
    OSVERSIONINFO info;
    info.dwOSVersionInfoSize = sizeof(info);

    if (!GetVersionEx(&info)) {
        return -1;
    }

    u->machine = "";

    switch (info.dwMajorVersion) {
    case 4:
        switch (info.dwMinorVersion) {
        case 0:
            u->sysname = "Microsoft Windows NT 4.0";
            break;
        case 10:
            u->sysname = "Microsoft Windows 98";
            break;
        case 90:
            u->sysname = "Microsoft Windows Me";
            break;
        default:
            return -1;
        }
        break;

    case 5:
        switch (info.dwMinorVersion) {
        case 0:
            u->sysname = "Microsoft Windows 2000";
            break;
        case 1:
            u->sysname = "Microsoft Windows XP";
            break;
        case 2:
            u->sysname = "Microsoft Server 2003";
            break;
        default:
            return -1;
        }
        break;

    default:
        return -1;
    }

    return 0;
}


text:
class PasswordChangeController < ApplicationController
  before_action :require_no_user
  before_action :require_email_user
  before_action :require_token

  def show
    respond_to do |format|
      format.json { head :no_content }
      format.html
    end
  end

  def create
    if email_user.change_password(params[:password], params[:password_confirmation])
      # Do not automatically log in the user
      respond_to do |format|
        format.json { head :no_content }
        format.html {
          flash.now[:notice] = "Password updated successfully"
          redirect_to(login_path)
        }
      end
    else
      respond_to do |format|
        format.json { render json: { status: 'error', errors: email_user.errors }.to_json, status: 422 }
        format.html { render :show }
      end
    end
  end

  protected

  # Any existing user should be logged out to prevent session leakage
  def require_no_user
    logout
  end

  # The token is paired with an email parameter so that the user can be
  # found in the database. Once found the tokens can be securely compared
  # to prevent timing attacks. The email address is chosen over the id
  # because the reset was generated using the email address and thus is
  # already known. Using the id would increase information leakage.
  def require_email_user
    deny_user("Invalid email address", root_path) if params[:email].blank? || email_user.blank?
  end

  def email_user
    return @user if defined?(@user)
    @user = User.where(email: params[:email]).first || raise(ActiveRecord::RecordNotFound)
  end

  # Reset password tokens expire after 1 day
  def require_token
    valid = params[:token].present?
    valid = valid && ActiveSupport::SecurityUtils.secure_compare(params[:token], email_user.reset_password_token)
    valid = valid && !email_user.reset_password_token_expired?
    deny_user("Invalid token", root_path) unless valid
  end

end


text:
package im.actor.model.cocoa;

import im.actor.model.jvm.JavaThreadingProvider;

public class CocoaThreadingProvider extends JavaThreadingProvider {
}


text:
namespace IECorePython
{
void bindMath();
}

#endif // IECOREPYTHON_MATHBINDING_H


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">QuizTemplate</string>
    <string name="pkgName">com.summerice.uscitizenshiptest</string>
    <string name="action_credits">Credits</string>
    <string name="detail_credits">Source Code by DontComplain</string>

</resources>