text:
<?php
error_reporting(0);
require('php/obtainfiles.php');
// Initialize session
session_start();

// Check, if username session is NOT set then this page will jump to login page
if ((!isset($_SESSION['username']))||(!isset($_SESSION['password']) )){
header('Location: ../');
}

?>

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="SHORTCUT ICON" href="images/rvce.ico">
    <link href='css/fullcalendar.css' rel='stylesheet' />
<link href='css/fullcalendar.print.css' rel='stylesheet' media='print' />

    <?php

    $host="localhost"; // Host name or server name
    $username="root"; // Mysql username
    $password=""; // Mysql password
    $db_name="placementinformer"; // Database name
    $tbl_name="student"; // Table name
    $con = mysqli_connect("$host", "$username", "$password","$db_name");
    if (mysqli_connect_errno()) {
        echo "Failed to connect to MySQL: " . mysqli_connect_error();
    }
    session_start();
    $uname =  $_SESSION['userNameT'];
    $result = mysqli_query($con,"SELECT * FROM dateofvisit;");
    if(!$result)
    {
        echo "error";
    }
    while($db_field = mysqli_fetch_assoc($result))
    {
        echo "title: '" . $db_field['NAME'] . "'";
        echo "start: '" . $db_field['DATE'] . "'";
    }echo ",";

    echo "";
    ?>

    <title>Placement Informer</title>

    <link href="css/bootstrap.min.css" rel="stylesheet">

    <link href="css/simple-sidebar.css" rel="stylesheet">

    <title>Student Home</title>

    <link href="assets/css/bootstrap.css" rel="stylesheet" />

    <link href="assets/css/font-awesome.min.css" rel="stylesheet" />

    <link href="assets/css/style.css" rel="stylesheet" />

    <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css' />
	<link href="gener/genericons.css" rel="stylesheet">
	<link href="css/index-css/main.css" rel="stylesheet" />

					<?php
						$host="localhost"; // Host name or server name
						$username="root"; // Mysql username
						$password=""; // Mysql password
						$db_name="placementinformer"; // Database name
						$tbl_name="student"; // Table name
						$con = mysqli_connect("$host", "$username", "$password","$db_name");
						if (mysqli_connect_errno()) {
						  echo "Failed to connect to MySQL: " . mysqli_connect_error();
						}
						session_start();
						$uname =  $_SESSION['userNameT'];
						$result = mysqli_query($con,"SELECT name FROM student where USN = '$uname';");

					?>

                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">

                </button>

Calender View

                    <?php
                    $result = mysqli_query($con,"SELECT * FROM SPC where USN = '$uname';");
                    if(mysqli_num_rows($result)>0)
                    {
                        echo "
PC View
";
                        echo "
Add students
";
                    }
                    ?>

Edit Profile

Change Password?

Logout

Change Password

                    <form class="form-horizontal" method="post" name =  "changePass" action = "<?php echo htmlspecialchars('php/changePassword.php');?>" id = "changePass">
                        <fieldset>

                                Current Password

                                    <input id="curpass" name="curpass" type="password" placeholder="Current Password" class="form-control input-md">

                                New Password

                                    <input id="newpass" name="newpass" type="password" placeholder="New Password" class="form-control input-md">

                                Confirm New Password

                                    <input id="connewpass" name="connewpass" type="password" placeholder="Confirm New Password" class="form-control input-md">

                        </fieldset>

                    Forgot password?
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="submit" name = "submit" class="btn btn-success" action = "<?php echo htmlspecialchars('php/changePassword.php');?>" id = "submit">Save changes</button>

                </form>

            <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>

Calender View

MicroSoft


text:
package com.lalalla.t.biyesheji;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class Add2Activity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
private RadioButton yibanxiangmu;
    private RadioGroup yibanxiangmuzu;
    private RadioButton yanxuzizhuxiangmu;
    private RadioButton dingxiangzizhuxiangmu;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_acivityadd2);

        yibanxiangmu = (RadioButton) findViewById(R.id.yibanxiangmu);
        yibanxiangmuzu = (RadioGroup) findViewById(R.id.yibanxiangmuzu);
        yanxuzizhuxiangmu = (RadioButton) findViewById(R.id.yanxuzizhuxiangmu);
        dingxiangzizhuxiangmu = (RadioButton) findViewById(R.id.dingxiangzizhuxiangmu);
        yibanxiangmu.setOnCheckedChangeListener(this);
        yanxuzizhuxiangmu.setOnCheckedChangeListener(this);
        dingxiangzizhuxiangmu.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(yibanxiangmu.isChecked()){
    yibanxiangmuzu.setVisibility(yibanxiangmuzu.VISIBLE);
}
        else {
            yibanxiangmuzu.setVisibility(yibanxiangmuzu.GONE);
        }

    }
}

redpajama_set_name: RedPajamaGithub


text:
/**
 * @author Kai - Ting (Danil) Ko
 *
 * The class is used as a client to receive and to send bytes according to
 * inputed size and iterations through TCP Protocol. It can be a stand alone
 * client or a cloned of a server to response to a particular client
 *
 */

package com.component;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

public class TCPClientSocketController extends SocketController
{
    private Socket mSocket;
    private DataOutputStream mOut;
    private DataInputStream mIn;

    /**
     * Constructor to initialize variables and to prepare the controller
     * as a cloned of the server to response to a particular client
     * @param pSocket the Socket that the controller will use
     */
    public TCPClientSocketController(Socket pSocket)
    {
        super(pSocket.getInetAddress(), pSocket.getPort());
        System.out.println("Server accepts a new client");
        TAG = "Default Server";

        mSocket = pSocket;

        mOut = null;
        mIn = null;
    }  // TCPClientSocketController

    /**
     * Constructor to initialize variables and to prepare the controller
     * as a stand alone TCP client
     * @param pAddress The address that the client will host on
     * @param pPort The port that the client will listen on
     */
    public TCPClientSocketController(InetAddress pAddress, int pPort)
    {
        super(pAddress, pPort);
        TAG = "Default Client";

        mSocket = null;

        mOut = null;
        mIn = null;
    }  // TCPClientSocketController

    @Override
    public void establishInputOutput()
    {
        try
        {
        	// If the socekt is null, create a new socket with the
        	// inputed address and port
            if(mSocket == null)
            {
                mSocket = new Socket(mAddress, mPort);
            }  // if

            // Create the output and input streams
            // and prinout successful message
            mOut = new DataOutputStream(mSocket.getOutputStream());
            mIn = new DataInputStream(mSocket.getInputStream());
            System.out.println( TAG + " Establish Success");
        }  // try
        catch(UnknownHostException pException)
        {
        	// Cannot connect to the server, prevent the thread from running
            pException.printStackTrace();
            System.out.println("Cannot establish connection to IP = " + mAddress);
            mRunning = false;
        }  // catch
        catch(IOException pException)
        {
        	// Cannot create the output and/or input streams,
        	// prevent the thread from running
            pException.printStackTrace();
            System.out.println("Cannot establish output");
            mRunning = false;
        }  // catch
    }  // establishInputOutput

    @Override
    public void run()
    {
    	// If the flag is false, the thread will exit and close
        if(mRunning == false)
        {
            return;
        }  // if

        // Make a test byte
        byte lTestByte = "A".getBytes()[0];

        // Continue to run until the flag is false
        while(mRunning)
        {
            try
            {
            	  // If it is a client socket for the server to respond to clients
                  if(TAG == "Server")
                  {
                	  // Prepare the byte array accroding to the inputed size
                	  byte [] lReceivedBytes = new byte[mSize];

                	  while(true)
                	  {
                		  mIn.readFully(lReceivedBytes);
	                	  // Only respond if received byte(s) are receive fully
	                	  if(lReceivedBytes[mSize - 1] == lTestByte)
	                	  {
	                		  // Set the send bytes as the received bytes
	                		  mSendBytes = lReceivedBytes;

	                		  // Print out message
	                		  System.out.println("TCP Received Message Client: " + mAddress);

	                		  // Send original bytes back to the client
	                		  mOut.write(mSendBytes, 0, mSendBytes.length);
	                		  mOut.flush();

	                		  // Set send bytes as null
	                		  mSendBytes = null;

	                		  break;
	                	  }  // if
                	  } // while
                    }  // if
                  	// If it is a stand alone client
                    else
                    {
                    		// Only send information if send bytes is not null
                            if(mSendBytes != null)
                            {
                            	// Fill the each element in the array
                                for(int lIndex = 0; lIndex < mSize; lIndex++)
                                {
                                    mSendBytes[lIndex] = lTestByte;
                                }  // for

                                // Prepare variables to store data
                                long mLatency = 0;
                                long lLatency = 0;
                                int lReceivedPacket = 0;

                                // Loop through the iteration
                                for(int lIndex = 0; lIndex < mIteration; lIndex++)
                                {
                                	// Set the start time for the RTT
                                    lLatency = System.currentTimeMillis();
                                    mOut.write(mSendBytes, 0, mSendBytes.length);
                                    mOut.flush();

                                    // Retrieve bytes
                                    byte [] lReceivedBytes = new byte[mSize];

                                    while(true)
                                    {
	                                    mIn.readFully(lReceivedBytes);
	                                    if(lReceivedBytes[mSize - 1] == lTestByte)
	                                    {
	                                    	lReceivedPacket++;
	                                        break;
	                                    }  // if
                                    }  // while
                                	// Calculate current RTT and add it to total latency
                                    lLatency = System.currentTimeMillis() - lLatency;
                                    mLatency = mLatency + lLatency;

                                    //System.out.println(TAG + " send and respond " + lReceivedByteLength + " bytes successfully at iteration " + lIndex);
                                }  // for

                                System.out.println("TCP: ");

                                // Calculate and printout RTT
                                float lRTT = 0;
                                if(mLatency > 0)
                                {
                                	lRTT = (float)(mLatency / (float)mIteration) / (float)(1000f);
                                }  // if
                                System.out.println("TCP Average RTT: " + lRTT + " s");

                                // Calculate and printout the number of lost packets
                                System.out.println("TCP Lost Packet: " + (mIteration - lReceivedPacket) + " Packet(s)");

                                // Calculate and printout effective throughput
                                // (Size per packet(B) * 8(b/B)) / Average RTT
                                float lThroughput  = 0;
                                if(mLatency > 0)
                                {
                                    lThroughput = (8 * mSize * lReceivedPacket) / (mLatency / 1000f);
                                }  // if
                                System.out.println("TCP Effective Throughput: " + lThroughput + " bps");

                                // Set send byte to null to avoid to transmit again
                                mSendBytes = null;
                            }  // if
                    }  // else

                // Sleep for DELAY time
                Thread.sleep(DELAY);
            }  // try
            catch(InterruptedException pException)
            {
            	// Exit the loop and close the thread
                pException.printStackTrace();
                mRunning = false;
            }  // catch
            catch (IOException pException)
            {
            	// Error in sending or receiving data
            	// Exit the loop and close the thread
                pException.printStackTrace();
                mRunning = false;
            }  // catch
         }  // while

        try
        {
        	// Close all input and output streams
            mOut.close();
            mIn.close();
        	// Close the socket
            mSocket.close();
        }
        catch (IOException pException)
        {
        	// Error in close the input or the out streams
            pException.printStackTrace();
        }  // catch
    }  // void run

    /**
     * Disable or enable Nagle's algorithm on the client socket
     * @param pInput The input to enable or to disable Nagle's algorithm
     *                true to enable and false to disable
     */
    public void setNoDelay(boolean pInput)
    {
        try
        {
            mSocket.setTcpNoDelay(pInput);
        }  // try
        catch (SocketException pException)
        {
            pException.printStackTrace();
        }  // catch
    }  // void setNoDelay

    /**
     * Set the traffic class for the client socket
     * @param pInput The input to for the traffic class for the client socket
     */
    public void setTraffic(int pInput)
    {
        try
        {
            mSocket.setTrafficClass(pInput);
        }  // try
        catch (SocketException pException)
        {
            pException.printStackTrace();
        }  // catch
    }  // void setTraffic
}  // TCPClientSocketController


text:
package com.philemonworks.selfdiagnose.test.xtra;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Locale;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

public class MockHttpResponse implements HttpServletResponse {
    public void addCookie(Cookie arg0) {
        // TODO Auto-generated method stub
    }

    public void addDateHeader(String arg0, long arg1) {
        // TODO Auto-generated method stub
    }

    public void addHeader(String arg0, String arg1) {
        // TODO Auto-generated method stub
    }

    public void addIntHeader(String arg0, int arg1) {
        // TODO Auto-generated method stub
    }

    public boolean containsHeader(String arg0) {
        // TODO Auto-generated method stub
        return false;
    }

    public String encodeRedirectURL(String arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    public String encodeRedirectUrl(String arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    public String encodeURL(String arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    public String encodeUrl(String arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    public void sendError(int arg0) throws IOException {
        // TODO Auto-generated method stub
    }

    public void sendError(int arg0, String arg1) throws IOException {
        // TODO Auto-generated method stub
    }

    public void sendRedirect(String arg0) throws IOException {
        // TODO Auto-generated method stub
    }

    public void setDateHeader(String arg0, long arg1) {
        // TODO Auto-generated method stub
    }

    public void setHeader(String arg0, String arg1) {
        // TODO Auto-generated method stub
    }

    public void setIntHeader(String arg0, int arg1) {
        // TODO Auto-generated method stub
    }

    public void setStatus(int arg0) {
        // TODO Auto-generated method stub
    }

    public void setStatus(int arg0, String arg1) {
        // TODO Auto-generated method stub
    }

    public void flushBuffer() throws IOException {
        // TODO Auto-generated method stub
    }

    public int getBufferSize() {
        // TODO Auto-generated method stub
        return 0;
    }

    public String getCharacterEncoding() {
        // TODO Auto-generated method stub
        return null;
    }

    public String getContentType() {
        // TODO Auto-generated method stub
        return null;
    }

    public Locale getLocale() {
        // TODO Auto-generated method stub
        return null;
    }

    public ServletOutputStream getOutputStream() throws IOException {
        // TODO Auto-generated method stub
        return null;
    }

    public PrintWriter getWriter() throws IOException {
        // TODO Auto-generated method stub
        return new PrintWriter(new StringWriter());
    }

    public boolean isCommitted() {
        // TODO Auto-generated method stub
        return false;
    }

    public void reset() {
        // TODO Auto-generated method stub
    }

    public void resetBuffer() {
        // TODO Auto-generated method stub
    }

    public void setBufferSize(int arg0) {
        // TODO Auto-generated method stub
    }

    public void setCharacterEncoding(String arg0) {
        // TODO Auto-generated method stub
    }

    public void setContentLength(int arg0) {
        // TODO Auto-generated method stub
    }

    public void setContentType(String arg0) {
        // TODO Auto-generated method stub
    }

    public void setLocale(Locale arg0) {
        // TODO Auto-generated method stub
    }
}


text:
import { Injectable } from '@angular/core';

@Injectable()
export class LuxuryService {

  getLuxuryItem() {
    return "I'm the Luxury service from lazy module";
  }
}


text:
from __future__ import absolute_import

__all__ = ['Process', 'current_process', 'active_children']

#
# Imports
#

import os
import sys
import signal
import itertools
import binascii

from .compat import bytes
try:
    from _weakrefset import WeakSet
except ImportError:
    WeakSet = None  # noqa

try:
    ORIGINAL_DIR = os.path.abspath(os.getcwd())
except OSError:
    ORIGINAL_DIR = None

#
# Public functions
#

def current_process():
    '''
    Return process object representing the current process
    '''
    return _current_process

def _cleanup():
    # check for processes which have finished
    for p in list(_current_process._children):
        if p._popen.poll() is not None:
            _current_process._children.discard(p)

def active_children(_cleanup=_cleanup):
    '''
    Return list of process objects corresponding to live child processes
    '''
    try:
        _cleanup()
    except TypeError:
       # called after gc collect so _cleanup does not exist anymore
       return []
    return list(_current_process._children)

class Process(object):
    '''
    Process objects represent activity that is run in a separate process

    The class is analagous to `threading.Thread`
    '''
    _Popen = None

    def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
            daemon=None, **_kw):
        assert group is None, 'group argument must be None for now'
        count = _current_process._counter.next()
        self._identity = _current_process._identity + (count,)
        self._authkey = _current_process._authkey
        if daemon is not None:
            self._daemonic = daemon
        else:
            self._daemonic = _current_process._daemonic
        self._tempdir = _current_process._tempdir
        self._semprefix = _current_process._semprefix
        self._unlinkfd = _current_process._unlinkfd
        self._parent_pid = os.getpid()
        self._popen = None
        self._target = target
        self._args = tuple(args)
        self._kwargs = dict(kwargs)
        self._name = name or type(self).__name__ + '-' + \
                     ':'.join(str(i) for i in self._identity)
        if _dangling is not None:
            _dangling.add(self)

    def run(self):
        '''
        Method to be run in sub-process; can be overridden in sub-class
        '''
        if self._target:
            self._target(*self._args, **self._kwargs)

    def start(self):
        '''
        Start child process
        '''
        assert self._popen is None, 'cannot start a process twice'
        assert self._parent_pid == os.getpid(), \
               'can only start a process object created by current process'
        assert not _current_process._daemonic, \
               'daemonic processes are not allowed to have children'
        _cleanup()
        if self._Popen is not None:
            Popen = self._Popen
        else:
            from .forking import Popen
        self._popen = Popen(self)
        self._sentinel = self._popen.sentinel
        _current_process._children.add(self)

    def terminate(self):
        '''
        Terminate process; sends SIGTERM signal or uses TerminateProcess()
        '''
        self._popen.terminate()

    def join(self, timeout=None):
        '''
        Wait until child process terminates
        '''
        assert self._parent_pid == os.getpid(), 'can only join a child process'
        assert self._popen is not None, 'can only join a started process'
        res = self._popen.wait(timeout)
        if res is not None:
            _current_process._children.discard(self)

    def is_alive(self):
        '''
        Return whether process is alive
        '''
        if self is _current_process:
            return True
        assert self._parent_pid == os.getpid(), 'can only test a child process'
        if self._popen is None:
            return False
        self._popen.poll()
        return self._popen.returncode is None

    def _get_name(self):
        return self._name

    def _set_name(self, value):
        assert isinstance(name, basestring), 'name must be a string'
        self._name = value
    name = property(_get_name, _set_name)

    def _get_daemon(self):
        return self._daemonic

    def _set_daemon(self, daemonic):
        assert self._popen is None, 'process has already started'
        self._daemonic = daemonic
    daemon = property(_get_daemon, _set_daemon)

    def _get_authkey(self):
        return self._authkey

    def _set_authkey(self, authkey):
        self._authkey = AuthenticationString(authkey)
    authkey = property(_get_authkey, _set_authkey)

    @property
    def exitcode(self):
        '''
        Return exit code of process or `None` if it has yet to stop
        '''
        if self._popen is None:
            return self._popen
        return self._popen.poll()

    @property
    def ident(self):
        '''
        Return identifier (PID) of process or `None` if it has yet to start
        '''
        if self is _current_process:
            return os.getpid()
        else:
            return self._popen and self._popen.pid

    pid = ident

    @property
    def sentinel(self):
        '''
        Return a file descriptor (Unix) or handle (Windows) suitable for
        waiting for process termination.
        '''
        try:
            return self._sentinel
        except AttributeError:
            raise ValueError("process not started")

    def __repr__(self):
        if self is _current_process:
            status = 'started'
        elif self._parent_pid != os.getpid():
            status = 'unknown'
        elif self._popen is None:
            status = 'initial'
        else:
            if self._popen.poll() is not None:
                status = self.exitcode
            else:
                status = 'started'

        if type(status) is int:
            if status == 0:
                status = 'stopped'
            else:
                status = 'stopped[%s]' % _exitcode_to_name.get(status, status)

        return '<%s(%s, %s%s)>' % (type(self).__name__, self._name,
                                   status, self._daemonic and ' daemon' or '')

    ##

    def _bootstrap(self):
        from . import util
        global _current_process

        try:
            self._children = set()
            self._counter = itertools.count(1)
            if sys.stdin is not None:
                try:
                    sys.stdin.close()
                    sys.stdin = open(os.devnull)
                except (OSError, ValueError):
                    pass
            old_process = _current_process
            _current_process = self
            try:
                util._finalizer_registry.clear()
                util._run_after_forkers()
            finally:
                # delay finalization of the old process object until after
                # _run_after_forkers() is executed
                del old_process
            util.info('child process calling self.run()')
            try:
                self.run()
                exitcode = 0
            finally:
                util._exit_function()
        except SystemExit, e:
            if not e.args:
                exitcode = 1
            elif isinstance(e.args[0], int):
                exitcode = e.args[0]
            else:
                sys.stderr.write(str(e.args[0]) + '\n')
                sys.stderr.flush()
                exitcode = 0 if isinstance(e.args[0], str) else 1
        except:
            exitcode = 1
            if not util.error('Process %s', self.name, exc_info=True):
                import traceback
                sys.stderr.write('Process %s:\n' % self.name)
                traceback.print_exc()
        finally:
            util.info('process exiting with exitcode %d', exitcode)
            sys.stdout.flush()
            sys.stderr.flush()
        return exitcode

#
# We subclass bytes to avoid accidental transmission of auth keys over network
#

class AuthenticationString(bytes):

    def __reduce__(self):
        from .forking import Popen

        if not Popen.thread_is_spawning():
            raise TypeError(
                'Pickling an AuthenticationString object is '
                'disallowed for security reasons')
        return AuthenticationString, (bytes(self),)

#
# Create object representing the main process
#

class _MainProcess(Process):

    def __init__(self):
        self._identity = ()
        self._daemonic = False
        self._name = 'MainProcess'
        self._parent_pid = None
        self._popen = None
        self._counter = itertools.count(1)
        self._children = set()
        self._authkey = AuthenticationString(os.urandom(32))
        self._tempdir = None
        self._semprefix = 'mp-' + binascii.hexlify(
                                os.urandom(4)).decode('ascii')
        self._unlinkfd = None

_current_process = _MainProcess()
del _MainProcess

#
# Give names to some return codes
#

_exitcode_to_name = {}

for name, signum in signal.__dict__.items():
    if name[:3] == 'SIG' and '_' not in name:
        _exitcode_to_name[-signum] = name

_dangling = WeakSet() if WeakSet is not None else None


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <title>src\view\template.js - yam</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.9.1/build/cssgrids/cssgrids-min.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">

            API Docs for: 0.2.0

APIs

Classes

Modules

            <input type="search" id="api-filter" placeholder="Type to filter APIs">

ya

ya.$Promise

ya.Collection

ya.collection.$Manager

ya.Controller

ya.controller.$Manager

ya.Core

ya.data.Action

ya.data.Proxy

ya.data.proxy.Localstorage

ya.Error

ya.event.$dispatcher

ya.Job

ya.Manager

ya.mixins.Array

ya.mixins.CoreStatic

ya.mixins.CSSStyle

ya.mixins.DOM

ya.mixins.GetSet

ya.mixins.Observable

ya.Model

ya.Router

ya.View

ya.view.$Manager

ya.view.TDOM

ya.view.Template

ya.view.template.$Manager

ya

        Show:

            <input type="checkbox" id="api-show-inherited" checked>
            Inherited

            <input type="checkbox" id="api-show-protected">
            Protected

            <input type="checkbox" id="api-show-private">
            Private

            <input type="checkbox" id="api-show-deprecated">
            Deprecated

File: src\view\template.js

/**
 * @namespace ya.view
 * @class Template
 * @extends ya.Core
 */
ya.Core.$extend({
    module: 'ya',
    alias: 'view.Template',
    static: {
        id: 0,
        DOM4: (function () {
            return !document.createAttribute('rel') instanceof Node;
        }),
        BindingType: {
            CSS: 5,
            VIEW: 4,
            TEXT: 3,
            ATTR: 2,
            COL: 1
        }
    },
    mixins: [
        ya.mixins.Array
    ],
    defaults: {
        id: null,
        /**
         * @attribute config.tpl
         * @type HTMLElement
         * @required
         */
        tpl: null,
        /**
         * @attribute config.tDOM TDOM object definition
         * @type {Object}
         */
        tDOM: null
    },
    init: function (opts) {
        var me = this;

        me
            .__super(opts)
            .initRegister()
            .initBindings();

    },
    initRequired: function () {
        var me = this;

        if (!me.getTpl()) {

            throw ya.Error.$create('ya.view.Template: Missing tpl property in configuration object', 'YVT1');

        }

        if (!me._html.hasChildNodes()) {

            throw ya.Error.$create(me.__class__ + ': Its seems that object doesnt contain any template', 'YVT2');

        }

        return me;
    },
    initDefaults: function () {
        var me = this,
            html = me.getTpl(),
            docFragment = document.createDocumentFragment();

        me.setId(me.getId() || 'template-' + ya.view.template.$Manager.getCount());
        me.setTDOM(me.getTDOM() || ya.view.TDOM);

        if (Array.isArray(html)) {
            html = html.join("");
        }

        if (typeof html === 'string' || html instanceof String) {
            var evaluated = document.createElement('div');

            evaluated.innerHTML = html;

            while (evaluated.hasChildNodes()) {

                docFragment.appendChild(evaluated.firstChild);

            }

        } else if (html instanceof DocumentFragment) {

            docFragment = html;

        } else if (html instanceof HTMLElement) {

            docFragment.appendChild(html.firstChild);

        }

        me.set('html', docFragment);

        return me;
    },
    initRegister: function () {
        var me = this;

        ya.view.template
            .$Manager.register(
                me.getId(),
                me
            );

        return me;
    },
    /**
     * @method initBindings
     * @returns {*}
     */
    initBindings: function () {
        var me = this,
            texts,
            attrs;

        attrs = me.findAttrsBindings();
        texts = me.findTextBindings();

        me.set('bindings', attrs.concat(texts));

        return me;
    },
    /**
     * @method findAttrsBindings
     */
    findAttrsBindings: function () {
        var me = this,
            attrs = [],
            bindings = [],
            regEx = /^ya-(.*)/i,
            nodeAttrs = [],
            __slice = Array.prototype.slice,
            binding,
            walker,
            match,
            attr,
            node;

        walker = document.createTreeWalker( // Create walker object and
            me._html,
            NodeFilter.SHOW_ELEMENT,
            null,
            false
        );

        while (walker.nextNode()) {
            // walk through all nodes

            node = walker.currentNode;
            // HTMLElement node
            // get all attributes
            // and push to array
            nodeAttrs = __slice.call(node.attributes);

            // check if contents of should be scan
            if (me.isTemplate(node)) {
                continue;
            }
            // DOM4 polyfill - attribute no longer inherits from Node
            // so we need to set owner element manually
            if (ya.view.Template.$DOM4) {
                /*jshint -W083 */
                me.each(nodeAttrs, function (attr) {
                    attr.ownerElement = node;
                });

            }

            attrs = attrs.concat(nodeAttrs);

        }
        // execute attribute processing

        while (attrs.length) {

            attr = attrs.pop();

            match = attr.nodeName.match(regEx);

            switch (match && match[1]) {
                case 'collection' :
                    binding = me.prepareColBindings(attr);
                    break;
                case 'view' :
                    binding = me.prepareViewBindings(attr);
                    break;
                case 'css' :
                    binding = me.prepareCSSBindings(attr);
                    break;
                default :
                    binding = me.prepareAttrBindings(attr);

            }

            if (binding) {
                bindings.push(binding);
            }

        }

        return bindings;
    },
    isTemplate: function (node) {

        node = node.parentNode;
        while (node.parentNode) {
            if (
                node.attributes.getNamedItem('ya-view') ||
                    node.attributes.getNamedItem('ya-collection')
                ) {
                return true;

            }

            node = node.parentNode;
        }

        return false;
    },
    findTextBindings: function () {
        var me = this,
            bindings = [],
            binding,
            walker;

        walker = document.createTreeWalker( // Create walker object and
            me._html,
            NodeFilter.SHOW_TEXT,
            null,
            false
        );

        while (walker.nextNode()) {
            // walk through all nodes

            binding = me.prepareTextBindings(walker.currentNode);
            if (binding) {
                bindings.push(binding);
            }

        }

        // we cant mess with DOM when we walking through it
        // so we need to replace text nodes after we found all
        // matches
        me.each(bindings, function (binding) {

            binding.old.parentNode.replaceChild(binding.doc, binding.old);

            delete binding.doc;
            delete binding.old;

        });

        return bindings;
    },
    prepareTextBindings: function (node) {
        var results = node.data.match(/\{\{(.*?)\}\}/gi),// we searching for mustached text inside it
            i, len, headers, header, binding = false;

        if (results) { // and if we have positive match
            var doc = document.createElement('span'),// we create new span element
            // and id for binding
                rId = ya.view.Template.$id++;

            doc.setAttribute('ya-id', rId); // and add generated id.

            i = 0;
            len = results.length;
            headers = [];

            // In the end we replace all match via data.
            while (i < len) {

                result = results[i++];
                header = result.substr(2, (result.length - 4)).split('.');
                headers.push(header);

            }

            // We also keep founded bindings.
            binding = {
                original: node.value || node.data,
                old: node,
                doc: doc,
                models: {},
                callbacks : [],
                headers: headers,
                type: 3,
                pointer: rId
            };

        }

        return binding;
    },
    prepareColBindings: function (attr) {
        var options = attr.value.match(/(?:class|id|namespace|model|view)[?!:]([\S]+)/gi),
            node = attr.ownerElement,
            rId = node.getAttribute('ya-id') || ya.view.Template.$id++,
            collection = {
                view: 'ya.View',
                class: 'ya.Collection'
            },
            binding = {
                pointer: rId,
                type: ya.view.Template.$BindingType.COL,
                collection: collection
            },
            DOM = ya.mixins.DOM,
            option;

        node.setAttribute('ya-id', rId);

        while (options && options.length) {

            option = options.pop().split(':');
            collection[option[0]] = option[1];

        }

        if (node.hasChildNodes()) {

            var tpl = ya.$factory({
                module: 'ya',
                alias: 'view.Template',
                tpl: DOM.removeChildren(node)
            });

            collection.tpl = tpl.getId();

        }

        return binding;
    },
    prepareViewBindings: function (attr) {
        var node = attr.ownerElement,
            view = node.getAttribute('ya-view') || 'ya.View',
            rId = node.getAttribute('ya-id') || ya.view.Template.$id++,
            options = attr.value.match(/(?:class|id)[?!:]([\w\.]+)/gi),
            binding = {
                pointer: rId,
                type: ya.view.Template.$BindingType.VIEW,
                view: {
                    class: 'ya.View'
                }
            },
            option;

        node.setAttribute('ya-id', rId);

        while (options && options.length) {
            option = options.pop().split(':');
            binding.view[option[0]] = option[1];
        }

        return binding;
    },
    prepareCSSBindings: function (attr) {
        var node = attr.ownerElement,
            results = attr.value && attr.value.match(/\{\{(.*?)\}\}/gi),
            len = results && results.length,
            headers = [], i = 0,
            original, binding, header, rId, style;

        rId = node.getAttribute('ya-id');
        if (!rId) {

            rId = ya.view.Template.$id++;
            node.setAttribute('ya-id', rId);

        }

        if (results) {

            while (i < len) {

                result = results[i++];
                header = result.substr(2, (result.length - 4)).split('.');
                headers.push(header);

            }

        }

        original = (node.getAttribute('style') || "") + attr.value;

        node.setAttribute('style', original);

        binding = {
            original: original,
            fillAttr: false,
            headers: headers,
            callbacks : [],
            models: {},
            name: 'style',
            type: ya.view.Template.$BindingType.ATTR,
            pointer: rId
        };

        return binding;
    },
    prepareAttrBindings: function (attr) {
        var node = attr.ownerElement,
            results = attr.value && attr.value.match(/\{\{(.*?)\}\}/gi),
            len = results && results.length,
            original = attr.value,
            headers = [], i = 0,
            binding, rId, header;

        if (results) {

            rId = node.getAttribute('ya-id');
            if (!rId) {

                rId = ya.view.Template.$id++;
                node.setAttribute('ya-id', rId);

            }

            while (i < len) {

                result = results[i++];
                header = result.substr(2, (result.length - 4)).split('.');
                headers.push(header);

            }

            binding = {
                fillAttr: ya.mixins.CSSStyle.isFillAttr(attr.name),
                name: attr.name,
                original: original,
                models: {},
                callbacks : [],
                headers: headers,
                type: ya.view.Template.$BindingType.ATTR,
                pointer: rId
            };

        }

        return results ? binding : null;
    },
    getTDOMInstance: function (view) {
        var me = this;

        return me.getTDOM().$create({
            config: {
                view: view,
                bindings: ya.$clone(me.get('bindings')),
                DOM: me.get('html').cloneNode(true)
            }
        });
    }
});


text:
class CreateArticle < ActiveRecord::Migration[5.1]
  def change
    create_table :articles do |t|
      t.string :title
      t.timestamps
    end
  end
end


text:
\chapter{Présentation de l'entreprise}

\section{VideoStitch}
\subsection{Présentation générale}
\begin{wrapfigure}[6]{r}{7cm}
  \centering
  \includegraphics[width=6cm]{images/videostitch-logo.jpg}
  \caption{Logo de VideoStitch}
\end{wrapfigure}
VideoStitch est une entreprise française d'édition de logiciels, qui conçoit et
vend des logiciels de capture, de montage, de montage, de diffusion et de lecture
de vidéos panoramiques à 360\degree. Elle s'intéresse par extension au marché de
la réalité virtuelle.
Son site internet est à l'adresse suivante : \url{http://www.video-stitch.com/}.\\
C'est une Société à Actions Simplifiées (SAS) basée sur Paris, qui emploie moins
d'une dizaine de personnes actuellement. La plupart ayant été embauchés il y a
quelques mois, c'est une société en forte croissance.
Nicolas Burtey en est le président.

\subsection{L'équipe}
L'équipe est actuellement composée de 8 personnes et d'un nombre variable de 2 à 5 stagiaires.\\
Nicolas Burtey et Aksel Piran sont en charge de
la partie commerciale et marketing de l'entreprise. Ils consacrent également
du temps dans la recherche d'investisseurs et la présentation de l'entreprise dans
des salons ou des conférences. En outre, M. Burtey suit l'avancement des produits
en passant un jour ou deux dans la semaine avec l'équipe des développeurs.\\
Nicolas Lopez, Wieland Morgenstern et Henri Rebecq travaillent sur le c\oe ur du
projet, \cf{videostitch-sdk-section}, mettant au point algorithmes et nouvelles fonctionnalités.\\
Andrés Peralta, Julien Fond et Raphaël Lemoine travaillent quant à eux à la conception
des trois autres produits de VideoStitch basés sur \nameref{videostitch-sdk-section}~:
\cf{videostitch-studio-section}, \cf{vahana-vr-section}, \cf{videostitch-player-section}.\\
Liesbeth De Mey, stagiaire, est en charge de réaliser des démonstrations et
des tutoriels vidéos des produits de l'entreprise. Enfin, Jean Duthon et Marie
Chatelin, stagiaires UTCéens également en TN09, sont en charge, respectivement,
de la \textit{QA}\footnote{\textit{Quality Assurance}} et de l'intégration continue
des quatre produits pour Jean, et d'assister l'équipe au développement des logiciels
pour Marie. Leurs rapports contiennent de plus amples détails sur le déroulé de
leurs stages.

\subsection{Historique}
VideoStitch a été fondée par ce même Nicolas Burtey en janvier 2012.\\
Photographe diplômé de l'École Lumière, s'étant fait connaître par la photo panoramique
et la photo fish-eye, M. Burtey évolue par la suite dans le domaine de la vidéo panoramique.\\
\begin{wrapfigure}[6]{l}{6cm}
  \centering
  \includegraphics[width=5cm]{images/loopin-logo.png}
  \caption{Logo de Loop'In}
\end{wrapfigure}
Il crée sa société de production vidéo, Loop'In, avec laquelle il réalise une
certain nombre de vidéos panoramiques à 360\degree pour le compte de divers clients (publicité essentiellement).
Des exemples de ces vidéos sont disponibles à cette adresse : \url{http://www.loop-in.com/galerie/}.
La vidéo panoramique, étant alors un procédé très jeune encore inconnu du grand public, est
lente et difficile à réaliser: beaucoup de tâches doivent être faites de manière
manuelle et répétitive, avec des outils inadaptés car non prévus à cette utilisation.
Si la création de photos panoramiques et à 360\degree est aisée, il manque toutefois
un logiciel complet et mature qui permettrait l'édition et le montage de vidéos panoramiques.\\
\newline
M. Burtey décide alors de créer VideoStitch pour concevoir cet outil, un logiciel
d'édition et de montage de vidéos panoramiques : VideoStitch Studio.
Quand ce logiciel atteint une version stable, en 2014, VideoStitch oriente alors
ses efforts vers un nouveau logiciel, Vahana VR, permettant cette fois ci une réalisation
et une diffusion en direct de vidéos panoramiques à 360\degree.\\
Le but de la société est de permettre une production aisée et de qualité de vidéos
panoramiques à 360\degree, de la capture des images à la diffusion de la vidéo finale,
en passant par sa réalisation complète.

\section{La vidéo 360}
\subsection{Du panorama à la vidéo 360}
Une image panoramique, ou panorama, est une superposition d'images qui sont assemblées
pour composer une vue bien plus large que ne le permet une image seule. La figure~
\ref{rochester-ny} présente un exemple d'assemblage d'un panorama.\\
Concrètement, avec un appareil photographique, cela consiste à prendre plusieurs vues
successives en tournant l'appareil autour d'un axe entre deux clichés.
Les photos obtenues forment ainsi une série d'un même sujet et doivent pouvoir
se recouvrir en partie pour être ensuite assemblées en une seule image panoramique.
Cet assemblage peut être réalisé avec directement par l'appareil, comme c'est le cas des
téléphones portables, ou par un logiciel spécialisé, comme Photoshop\cite{photomerge}
ou PTgui\cite{PTgui}.
\begin{figure}
  \centering
  \includegraphics[width=11cm]{images/rochester-ny.png}
  \caption{Exemple d'assemblage de panorama avec détection des zones de recouvrement\cite{RochesterNY}}
  \label{rochester-ny}
\end{figure}
\newline
La vidéo panoramique consiste à filmer avec plusieurs caméras en même temps, chacune
capturant une partie du panorama, pour assembler les images capturées en une seule
vidéo par le même principe que la photo panoramique.\\
Avec suffisamment de caméras, il est possible de couvrir un angle de prise de vue
de 360\degree à l'horizontale et de 180\degree à la verticale. Le panorama créé
forme alors une sphère virtuelle, comme le montre la figure~\ref{camera-projection}.
C'est ce qu'on appelle la vidéo 360.
\begin{figure}
  \centering
  \includegraphics[width=6.5cm]{images/camera-projection.png}
  \caption{Exemple d'une scène filmée avec une caméra}
  \label{camera-projection}
\end{figure}
\newline
Cependant, comme le montre la figure~\ref{rochester-ny}, un panorama reste une image
$-$ ou une vidéo $-$, c'est-à-dire une matrice plane constituée de pixels\footnote{Pour
 \enquote{picture element}}. Or une vidéo 360 représentant une sphère virtuelle, ou
plutôt sa surface, elle sera nécessairement une \emph{projection} de cette sphère,
c'est-à-dire une correspondance mathématique entre cette surface en 3 dimensions
et cette vidéo plane\cite{projection-cartographique}.\\
Dans la vidéo 360, la projection la plus utilisée est la projection équirectangulaire\cite{what-is-equirectangular}.
Un exemple en est le planisphère terrestre, où après une projection cylindrique équirectangulaire
sur la figure~\ref{projection-cylindrique} le plan est déroulé pour obtenir le
planisphère de la figure~\ref{planisphère}.
\begin{figure}
  \centering
  \begin{minipage}[t]{0.35\textwidth}
    \centering
    \includegraphics[width=3.4cm]{images/projection-cylindrique.png}
    \captionof{figure}{Schéma d'une projection équirectangulaire\cite{projection-cylindrique}}
    \label{projection-cylindrique}
  \end{minipage}%
  \hspace{0.04\textwidth}
  \begin{minipage}[t]{0.6\textwidth}
    \centering
    \includegraphics[width=8.5cm]{images/equirectangular-projection.jpg}
    \captionof{figure}{Projection équirectangulaire de la Terre\cite{planisphere}}
    \label{planisphère}
  \end{minipage}
\end{figure}
\newline
Un lecteur vidéo 360 est alors nécessaire pour lire correctement la vidéo~:
il va reconstruire la sphère, pour y projeter le panorama et y placer le
spectateur au centre de cette sphère. Dès lors, le spectateur peut déplacer le
regard tout autour de lui pour embrasser le panorama : on entre dans le champ de
la réalité virtuelle\footnote{La réalité virtuelle est ici comprise dans son sens
  de \enquote{Simulation sensorielle immersive de la réalité}\cite{definition-rv}}.

\subsection{Le marché de la vidéo 360}
Si les années 2000 ont vu la démocratisation des appareils photographiques numériques,
les années 2010 voient l'émergence des caméras numériques Haute
Définition\footnote{Définition d'image de 1920x1080 pixels} bon marché, comme les GoPro,
et des écrans 4K\footnote{Définition d'image de 4096x2160 pixels}. De plus les capacités
informatiques grand public permettent désormais de stocker et traiter plusieurs
vidéos HD en même temps.\\
Dès lors la vidéo 360 peut se développer, son coût technique
étant accessible, et le marché, bien qu'encore restreint et méconnu du public,
est un plein développement et présente déjà de très nombreux concurrents. Jaunt,
entreprise américaine créée en mai 2013 a, par exemple, déjà levé 35 millions
de dollars de fonds d'investissement\cite{jaunt-fundings}.\\
Les grandes entreprises comme Facebook\cite{facebook-vr}, Samsung\cite{samsung-vr},
Microsoft\cite{microsoft-vr} ou Google\cite{google-vr} suivent de
très près ce marché, notamment pour concevoir des produits de réalité virtuelle
ou de réalité augmentée, qui progressivement vont s'installer dans les usages
du public, tout comme l'ont fait auparavant les ordinateurs portables, les téléphones mobiles
et les tablettes numériques.\\

\section{Produits et stratégies de l'entreprise}
Par rapport à ce marché, VideoStitch se positionne aujourd'hui comme un challenger
et propose actuellement quatre produits\cite{videostitch-products}.
\subsection{VideoStitch Studio}
\label{videostitch-studio-section}
\label{videostitch-studio}
%\begin{wrapfigure}[5]{r}{5cm}
%  \centering
%  \includegraphics[width=4cm]{images/studio.png}
%  \caption{Logo de VideoStitch Studio}
%\end{wrapfigure}
Premier logiciel de l'entreprise, sortis en version stable en 2013 pour Windows, Mac OS X et Linux,
il permet une conception de vidéos 360. Le \textit{workflow} de travail avec le logiciel est le suivant :
\subsubsection{Importation des vidéos}
\label{importation-videos}
Le cas le plus commun est de capturer la vidéo 360 à l'aide de 6 caméras GoPro
installées sur une monture spécialisée\footnote{Aussi appelée \textit{rig}} comme sur la figure~\ref{rig}.
Les caméras sont configurées pour filmer en HD, et, munies de leurs optiques
d'origine, six sont nécessaires pour filmer toute la sphère du panorama.
\begin{figure}
  \centering
  \begin{minipage}[b]{0.3\textwidth}
    \centering
    \includegraphics[width=3cm]{images/rig.png}
    \caption{Une monture 360}
    \label{rig}
  \end{minipage}%
  \hspace{0.04\textwidth}
  \begin{minipage}[b]{0.65\textwidth}
    \centering
    \includegraphics[width=9cm]{images/studio-sources-numeros.jpg}
    \caption{Les 6 fichiers vidéos source numérotés importés dans Studio}
    \label{importation}
  \end{minipage}
\end{figure}

\subsubsection{Synchronisation des vidéos}
Lors de la capture, les caméras sont bien souvent démarrées en décalées. Il s'agit
donc de resynchroniser les vidéos enregistrées.\\
Pour cela, la méthode la plus pratique est le \textit{motion},
où le logiciel analyse les mouvements de chaque vidéo : en effet les caméras étant fixées
sur la même monture, elles ont donc décris les mêmes mouvements dans l'espace, mais
en décalé sur les vidéos.

\subsubsection{Calibration}
À cette étape est reconstituée la sphère; ce qui consiste à retrouver la
position relative de chaque caméra par rapport à la monture.\\
À un même instant des vidéos, choisis par l'utilisateur, le logiciel trouve des
points de contrôle entre les images des différentes caméras, c'est-à-dire des
points identiques de la scène présents sur au moins deux images. C'est ici que les
zones de recouvrements entre les images trouvent leur importance.\\
Une fois les points trouvés, les vidéos peuvent être superposées et être assemblées
\footnote{C'est ce qu'on appelle le \textit{stitch}}.
\begin{figure}
  \centering
  \includegraphics[width=11cm]{images/studio-output-angles-numeros.jpg}
  \caption{Équirectangulaire avec angle de capture colorisés et numéros des 6 sources}
\end{figure}

\subsubsection{Correction d'exposition}
Chaque caméra ayant filmé dans une direction, les captures vidéos auront chacune
des expositions différentes. De même, les balances des blancs peuvent différer
entre les vidéos. Le logiciel corrige localement ces deux paramètres pour homogénéiser
le panorama final.

\subsubsection{Stabilisation}
La stabilisation consiste à lisser les micros mouvements des vidéos, qui ont
pu se produire lors de la capture, par exemple si la monture s'est déplacée dans l'espace lors
de l'enregistrement. Cette étape est nécessaire : regarder dans un casque de réalité
virtuelle une vidéo non stabilisée est très désagréable.

\subsubsection{Correction de l'orientation}
Il s'agit simplement ici de redonner sens aux notions de haut et de bas dans la
vidéo 360. En effet, si la calibration a permis de retrouver les positions des
caméras par rapport à la monture, le logiciel n'a aucune information sur la position
de la monture par rapport à la scène. Comme le montre la figure~\ref{orientation},
la correction s'effectue par un clic de souris enfoncé
et glissé jusqu'à déplacer l'équirectangulaire dans la position voulue. Un bon résultat
est obtenu quand l'horizon est redressé.
\begin{figure}
  \centering
  \begin{minipage}{0.45\textwidth}
    \centering
    \includegraphics[width=8.0cm]{images/studio-output-exposure-grid.jpg}
  \end{minipage}%
  \hspace{0.08\textwidth}
  \begin{minipage}{0.45\textwidth}
    \centering
    \includegraphics[width=8.0cm]{images/studio-output-exposure-grid-oriented.jpg}
  \end{minipage}
  \caption{Correction de l'orientation : l'horizon est redressé}
  \label{orientation}
\end{figure}

\subsubsection{Exportation}
\label{exportation}
Enfin, la vidéo 360 peut être exportée sous la forme d'un équirectangulaire, avec
possibilité d'intégrer le son d'une des caméras.

\begin{figure}
  \centering
  \includegraphics[width=11cm]{images/studio-equirectangular.jpg}
  \caption{Équirectangulaire final}
\end{figure}

\subsection{Vahana VR}
\label{vahana-vr-section}
%\begin{wrapfigure}[7]{r}{4cm}
%  \centering
%  \includegraphics[width=3cm]{images/vahanavr.png}
%  \caption{Logo de Vahana VR}
%\end{wrapfigure}
Ce nouveau logiciel, dont la sortie stable devrait s'effectuer en février 2015 uniquement sous Windows,
permet de réaliser le travail de Studio en temps réel, ainsi qu'une diffusion
de l'export en \textit{streaming live}. Les vidéos sont ici directement capturées des
caméras via des cartes d'acquisitions, et après une étape de calibration, sont
assemblées automatiquement. Le logiciel assure lui-même la bonne synchronisation
des vidéos.\\
Le panorama peut être alors exporté sur différents flux en même temps :
streaming RTMP, via une carte d'acquisition pour une sortie HDMI ou SDI, sur le
disque dur. Ce logiciel ouvre la possibilité du \textit{streaming} 360 à des événements
\textit{live}, comme les concerts, le sport, les défilés ou encore les conférences.
\begin{figure}
  \centering
  \begin{minipage}{0.45\textwidth}
    \centering
    \includegraphics[width=8.0cm]{images/vahana-vr-sources.jpg}
    \caption{6 entrées vidéos sur Vahana VR}
  \end{minipage}%
  \hspace{0.08\textwidth}
  \begin{minipage}{0.45\textwidth}
    \centering
    \includegraphics[width=8.0cm]{images/vahana-vr-output.jpg}
    \caption{Équirectangulaire assemblé après calibration des vidéos}
  \end{minipage}
\end{figure}

\subsection{VideoStitch Player}
\label{videostitch-player-section}
%\begin{wrapfigure}[7]{r}{4cm}
%  \centering
%  \includegraphics[width=3cm]{images/player.png}
%  \caption{Logo de VideoStitch Player}
%\end{wrapfigure}
C'est un lecteur de vidéo 360, développé par Alexis Pontin lors de son TN10 au précédent
semestre de Printemps 2014, sous Windows, Mac OS X et Linux. Le logiciel permet de lire des vidéos 360 depuis un
fichier vidéo équirectangulaire ou depuis un flux RTMP de Vahana VR. La vidéo peut-être
lue dans un mode interactif avec utilisation de la souris pour déplacer le regard,
ou en mode Oculus Rift, où elle est projetée dans le casque de réalité virtuelle.
L'utilisation du casque est tout à fait naturelle : le casque disposant d'un gyroscope
et d'un accéléromètre, il renvoie au lecteur la position de la tête de l'utilisateur.\\
Regarder une vidéo avec l'Oculus Rift depuis un flux RTMP de Vahana VR est une
expérience toute à fait singulière : le regard est téléporté à la place de la caméra.
Il est possible de se voir soi-même en direct, créant un dédoublement du corps et du regard
\footnote{Une démonstration est disponible en ligne : \url{https://www.youtube.com/watch?v=fQGLqAg0eRU}}.
\begin{figure}
  \centering
  \begin{minipage}{0.45\textwidth}
     \centering
     \includegraphics[width=7cm]{images/player-interactive.jpg}
     \caption{Vue interactive dans le Player, de l'équirectangulaire exporté}
  \end{minipage}%
  \hspace{0.08\textwidth}
  \begin{minipage}{0.45\textwidth}
    \centering
    \includegraphics[width=7cm]{images/player-oculus.jpg}
    \caption{Vue Oculus dans le Player, de l'équirectangulaire exporté}
  \end{minipage}
\end{figure}

\subsection{VideoStitch SDK}
\label{videostitch-sdk-section}
\begin{wrapfigure}[7]{r}{4cm}
  \centering
  \includegraphics[width=3.5cm]{images/cuda-logo.jpg}
  \caption{CUDA}
\end{wrapfigure}
Ces applications s'appuient toute trois sur une librairie développée séparément,
en C++/CUDA. C'est cette librairie qui implémente et exécute tous les algorithmes
de synchronisation, calibration, gestions des flux vidéos et audio et corrections
vidéos.
Toutes ces opérations sont très coûteuses en temps de calcul. C'est pourquoi
la techologie CUDA de nVidia est utilisée pour exploiter le potentiel de la carte
graphique\footnote{Ou \textit{GPU} pour \textit{Graphics Processing Unit}}.
En effet un \textit{GPU} est composé de milliers de c\oe urs fonctionnant en parallèles.
Or la librairie travaille sur des images vidéos, c'est-à-dire des matrices de pixels,
avec des calculs massivement parallélisables\cite{videostitch-cuda}.\\
\newline
Cette librairie est distribuée sous forme de \textit{SDK}\footnote{\textit{Software Development Kit}}, sous Windows, Mac OS X et Linux,
pour des clients souhaitant concevoir leur propre caméra ou un logiciel exploitant
les opérations \textit{stitch}.

\subsection{Stratégies}
Si VideoStitch est pendant un certain temps restée une petite start-up développant
un outil de post-production pour vidéos 360 \footnote{\cf{videostitch-studio}},
l'entreprise ambitionne désormais d'être le leader du marché.\\
Le marché est encore jeune, mais se décidera certainement en 2015 et s'alignera
probablement sur un leader. La technologie sera suffisamment mature, et des rachats
par de grands groupe sont probables, comme cela s'est produit dans le marché de la
réalité virtuelle en 2014, avec le rachat de l'Oculus Rift par Facebook
\cite{facebook-vr} par exemple.\\
Ce marché permettra également l'émergence de nouveaux contenus 360 pour les appareils
de réalité virtuelle, comme du cinéma ou de la télévision 360.
VideoStitch Studio et Vahana VR sont déjà des outils pertinents pour créer ces
nouveaux types de contenus, en particulier Vahana VR pour le streaming 360 en direct.
Pour cela il est important que Vahana VR soit le premier produit sur le marché
de la 360 \textit{live} et qu'il en prenne la tête~: c'est l'opportunité pour VideoStitch
de \enquote{décoller}.\\
\newline
Cependant d'autres pistes seront ensuite à développer. En effet, avec ces quatre produits
l'entreprise se destinerait seulement à une position de service par rapport à des
entreprises développant des services 360 ou des vidéos 360. Le développement d'une solution complète incluant une
caméra permettrait de dépasser cette position et atteindre le segment du grand public, incluant
les entreprises non spécialisées dans la production vidéo ou la réalité virtuelle.


text:
namespace mozc {
namespace usage_stats {

TEST(UploadUtilTest, UploadTest) {
  HTTPClientMock client;
  HTTPClient::SetHTTPClientHandler(&client);
  const string base_url = "http://clients4.google.com/tbproxy/usagestats";
  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&Count:c=100";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddCountValue("Count", 100);
    EXPECT_TRUE(uploader.Upload());

    uploader.RemoveAllValues();
    result.expected_request = "Test&100";
    client.set_result(result);
    EXPECT_TRUE(uploader.Upload());

    uploader.AddCountValue("Count", 1000);
    EXPECT_FALSE(uploader.Upload());
  }

  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&Timing:t=20;20;10;30";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddTimingValue("Timing", 20, 20, 10, 30);
    EXPECT_TRUE(uploader.Upload());
  }

  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&Integer:i=-10";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddIntegerValue("Integer", -10);
    EXPECT_TRUE(uploader.Upload());
  }

  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&Boolean:b=f";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddBooleanValue("Boolean", false);
    EXPECT_TRUE(uploader.Upload());
  }

  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&C:c=1&T:t=1;1;1;1&I:i=1&B:b=t";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddCountValue("C", 1);
    uploader.AddTimingValue("T", 1, 1, 1, 1);
    uploader.AddIntegerValue("I", 1);
    uploader.AddBooleanValue("B", true);
    EXPECT_TRUE(uploader.Upload());
  }
}

TEST(UploadUtilTest, UploadSecureTest) {
  HTTPClientMock client;
  HTTPClient::SetHTTPClientHandler(&client);
  const string base_url = "https://clients4.google.com/tbproxy/usagestats";
  {
    HTTPClientMock::Result result;
    result.expected_url = base_url + "?sourceid=ime&hl=ja&v=test";
    result.expected_request = "Test&100&Count:c=100";
    client.set_result(result);

    UploadUtil uploader;
    vector<pair<string, string> > params;
    params.push_back(make_pair("hl", "ja"));
    params.push_back(make_pair("v", "test"));
    uploader.SetHeader("Test", 100, params);
    uploader.AddCountValue("Count", 100);
    uploader.SetUseHttps(true);
    EXPECT_TRUE(uploader.Upload());

    uploader.RemoveAllValues();
    result.expected_request = "Test&100";
    client.set_result(result);
    EXPECT_TRUE(uploader.Upload());

    uploader.AddCountValue("Count", 1000);
    EXPECT_FALSE(uploader.Upload());
  }
}
}  // namespace usage_stats
}  // namespace mozc


text:
@interface SpinnerViewController : UIViewController
@end


text:
<?php
/**
 * Job queue runner utility methods
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @ingroup JobQueue
 */

use MediaWiki\Logger\LoggerFactory;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;

/**
 * Job queue runner utility methods
 *
 * @ingroup JobQueue
 * @since 1.24
 */
class JobRunner implements LoggerAwareInterface {
	/** @var callable|null Debug output handler */
	protected $debug;

	/**
	 * @var LoggerInterface $logger
	 */
	protected $logger;

	const MAX_ALLOWED_LAG = 3; // abort if more than this much DB lag is present
	const LAG_CHECK_PERIOD = 1.0; // check slave lag this many seconds
	const ERROR_BACKOFF_TTL = 1; // seconds to back off a queue due to errors

	/**
	 * @param callable $debug Optional debug output handler
	 */
	public function setDebugHandler( $debug ) {
		$this->debug = $debug;
	}

	/**
	 * @param LoggerInterface $logger
	 * @return void
	 */
	public function setLogger( LoggerInterface $logger ) {
		$this->logger = $logger;
	}

	/**
	 * @param LoggerInterface $logger
	 */
	public function __construct( LoggerInterface $logger = null ) {
		if ( $logger === null ) {
			$logger = LoggerFactory::getInstance( 'runJobs' );
		}
		$this->setLogger( $logger );
	}

	/**
	 * Run jobs of the specified number/type for the specified time
	 *
	 * The response map has a 'job' field that lists status of each job, including:
	 *   - type   : the job type
	 *   - status : ok/failed
	 *   - error  : any error message string
	 *   - time   : the job run time in ms
	 * The response map also has:
	 *   - backoffs : the (job type => seconds) map of backoff times
	 *   - elapsed  : the total time spent running tasks in ms
	 *   - reached  : the reason the script finished, one of (none-ready, job-limit, time-limit,
	 *  memory-limit)
	 *
	 * This method outputs status information only if a debug handler was set.
	 * Any exceptions are caught and logged, but are not reported as output.
	 *
	 * @param array $options Map of parameters:
	 *    - type     : the job type (or false for the default types)
	 *    - maxJobs  : maximum number of jobs to run
	 *    - maxTime  : maximum time in seconds before stopping
	 *    - throttle : whether to respect job backoff configuration
	 * @return array Summary response that can easily be JSON serialized
	 */
	public function run( array $options ) {
		global $wgJobClasses, $wgTrxProfilerLimits;

		$response = [ 'jobs' => [], 'reached' => 'none-ready' ];

		$type = isset( $options['type'] ) ? $options['type'] : false;
		$maxJobs = isset( $options['maxJobs'] ) ? $options['maxJobs'] : false;
		$maxTime = isset( $options['maxTime'] ) ? $options['maxTime'] : false;
		$noThrottle = isset( $options['throttle'] ) && !$options['throttle'];

		// Bail if job type is invalid
		if ( $type !== false && !isset( $wgJobClasses[$type] ) ) {
			$response['reached'] = 'none-possible';
			return $response;
		}
		// Bail out if DB is in read-only mode
		if ( wfReadOnly() ) {
			$response['reached'] = 'read-only';
			return $response;
		}
		// Bail out if there is too much DB lag.
		// This check should not block as we want to try other wiki queues.
		list( , $maxLag ) = wfGetLB( wfWikiID() )->getMaxLag();
		if ( $maxLag >= self::MAX_ALLOWED_LAG ) {
			$response['reached'] = 'slave-lag-limit';
			return $response;
		}

		// Flush any pending DB writes for sanity
		wfGetLBFactory()->commitAll( __METHOD__ );

		// Catch huge single updates that lead to slave lag
		$trxProfiler = Profiler::instance()->getTransactionProfiler();
		$trxProfiler->setLogger( LoggerFactory::getInstance( 'DBPerformance' ) );
		$trxProfiler->setExpectations( $wgTrxProfilerLimits['JobRunner'], __METHOD__ );

		// Some jobs types should not run until a certain timestamp
		$backoffs = []; // map of (type => UNIX expiry)
		$backoffDeltas = []; // map of (type => seconds)
		$wait = 'wait'; // block to read backoffs the first time

		$group = JobQueueGroup::singleton();
		$stats = RequestContext::getMain()->getStats();
		$jobsPopped = 0;
		$timeMsTotal = 0;
		$startTime = microtime( true ); // time since jobs started running
		$lastCheckTime = 1; // timestamp of last slave check
		do {
			// Sync the persistent backoffs with concurrent runners
			$backoffs = $this->syncBackoffDeltas( $backoffs, $backoffDeltas, $wait );
			$blacklist = $noThrottle ? [] : array_keys( $backoffs );
			$wait = 'nowait'; // less important now

			if ( $type === false ) {
				$job = $group->pop(
					JobQueueGroup::TYPE_DEFAULT,
					JobQueueGroup::USE_CACHE,
					$blacklist
				);
			} elseif ( in_array( $type, $blacklist ) ) {
				$job = false; // requested queue in backoff state
			} else {
				$job = $group->pop( $type ); // job from a single queue
			}

			if ( $job ) { // found a job
				++$jobsPopped;
				$popTime = time();
				$jType = $job->getType();

				WebRequest::overrideRequestId( $job->getRequestId() );

				// Back off of certain jobs for a while (for throttling and for errors)
				$ttw = $this->getBackoffTimeToWait( $job );
				if ( $ttw > 0 ) {
					// Always add the delta for other runners in case the time running the
					// job negated the backoff for each individually but not collectively.
					$backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
						? $backoffDeltas[$jType] + $ttw
						: $ttw;
					$backoffs = $this->syncBackoffDeltas( $backoffs, $backoffDeltas, $wait );
				}

				$info = $this->executeJob( $job, $stats, $popTime );
				if ( $info['status'] !== false || !$job->allowRetries() ) {
					$group->ack( $job ); // succeeded or job cannot be retried
				}

				// Back off of certain jobs for a while (for throttling and for errors)
				if ( $info['status'] === false && mt_rand( 0, 49 ) == 0 ) {
					$ttw = max( $ttw, self::ERROR_BACKOFF_TTL ); // too many errors
					$backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
						? $backoffDeltas[$jType] + $ttw
						: $ttw;
				}

				$response['jobs'][] = [
					'type'   => $jType,
					'status' => ( $info['status'] === false ) ? 'failed' : 'ok',
					'error'  => $info['error'],
					'time'   => $info['timeMs']
				];
				$timeMsTotal += $info['timeMs'];

				// Break out if we hit the job count or wall time limits...
				if ( $maxJobs && $jobsPopped >= $maxJobs ) {
					$response['reached'] = 'job-limit';
					break;
				} elseif ( $maxTime && ( microtime( true ) - $startTime ) > $maxTime ) {
					$response['reached'] = 'time-limit';
					break;
				}

				// Don't let any of the main DB slaves get backed up.
				// This only waits for so long before exiting and letting
				// other wikis in the farm (on different masters) get a chance.
				$timePassed = microtime( true ) - $lastCheckTime;
				if ( $timePassed >= self::LAG_CHECK_PERIOD || $timePassed < 0 ) {
					try {
						wfGetLBFactory()->waitForReplication( [
							'ifWritesSince' => $lastCheckTime,
							'timeout' => self::MAX_ALLOWED_LAG
						] );
					} catch ( DBReplicationWaitError $e ) {
						$response['reached'] = 'slave-lag-limit';
						break;
					}
					$lastCheckTime = microtime( true );
				}
				// Don't let any queue slaves/backups fall behind
				if ( $jobsPopped > 0 && ( $jobsPopped % 100 ) == 0 ) {
					$group->waitForBackups();
				}

				// Bail if near-OOM instead of in a job
				if ( !$this->checkMemoryOK() ) {
					$response['reached'] = 'memory-limit';
					break;
				}
			}
		} while ( $job ); // stop when there are no jobs

		// Sync the persistent backoffs for the next runJobs.php pass
		if ( $backoffDeltas ) {
			$this->syncBackoffDeltas( $backoffs, $backoffDeltas, 'wait' );
		}

		$response['backoffs'] = $backoffs;
		$response['elapsed'] = $timeMsTotal;

		return $response;
	}

	/**
	 * @param Job $job
	 * @param BufferingStatsdDataFactory $stats
	 * @param float $popTime
	 * @return array Map of status/error/timeMs
	 */
	private function executeJob( Job $job, $stats, $popTime ) {
		$jType = $job->getType();
		$msg = $job->toString() . " STARTING";
		$this->logger->debug( $msg );
		$this->debugCallback( $msg );

		// Run the job...
		$rssStart = $this->getMaxRssKb();
		$jobStartTime = microtime( true );
		try {
			$status = $job->run();
			$error = $job->getLastError();
			$this->commitMasterChanges( $job );

			DeferredUpdates::doUpdates();
			$this->commitMasterChanges( $job );
		} catch ( Exception $e ) {
			MWExceptionHandler::rollbackMasterChangesAndLog( $e );
			$status = false;
			$error = get_class( $e ) . ': ' . $e->getMessage();
			MWExceptionHandler::logException( $e );
		}
		// Always attempt to call teardown() even if Job throws exception.
		try {
			$job->teardown();
		} catch ( Exception $e ) {
			MWExceptionHandler::logException( $e );
		}

		// Commit all outstanding connections that are in a transaction
		// to get a fresh repeatable read snapshot on every connection.
		// Note that jobs are still responsible for handling slave lag.
		wfGetLBFactory()->commitAll( __METHOD__ );
		// Clear out title cache data from prior snapshots
		LinkCache::singleton()->clear();
		$timeMs = intval( ( microtime( true ) - $jobStartTime ) * 1000 );
		$rssEnd = $this->getMaxRssKb();

		// Record how long jobs wait before getting popped
		$readyTs = $job->getReadyTimestamp();
		if ( $readyTs ) {
			$pickupDelay = max( 0, $popTime - $readyTs );
			$stats->timing( 'jobqueue.pickup_delay.all', 1000 * $pickupDelay );
			$stats->timing( "jobqueue.pickup_delay.$jType", 1000 * $pickupDelay );
		}
		// Record root job age for jobs being run
		$rootTimestamp = $job->getRootJobParams()['rootJobTimestamp'];
		if ( $rootTimestamp ) {
			$age = max( 0, $popTime - wfTimestamp( TS_UNIX, $rootTimestamp ) );
			$stats->timing( "jobqueue.pickup_root_age.$jType", 1000 * $age );
		}
		// Track the execution time for jobs
		$stats->timing( "jobqueue.run.$jType", $timeMs );
		// Track RSS increases for jobs (in case of memory leaks)
		if ( $rssStart && $rssEnd ) {
			$stats->increment( "jobqueue.rss_delta.$jType", $rssEnd - $rssStart );
		}

		if ( $status === false ) {
			$msg = $job->toString() . " t=$timeMs error={$error}";
			$this->logger->error( $msg );
			$this->debugCallback( $msg );
		} else {
			$msg = $job->toString() . " t=$timeMs good";
			$this->logger->info( $msg );
			$this->debugCallback( $msg );
		}

		return [ 'status' => $status, 'error' => $error, 'timeMs' => $timeMs ];
	}

	/**
	 * @return int|null Max memory RSS in kilobytes
	 */
	private function getMaxRssKb() {
		$info = wfGetRusage() ?: [];
		// see http://linux.die.net/man/2/getrusage
		return isset( $info['ru_maxrss'] ) ? (int)$info['ru_maxrss'] : null;
	}

	/**
	 * @param Job $job
	 * @return int Seconds for this runner to avoid doing more jobs of this type
	 * @see $wgJobBackoffThrottling
	 */
	private function getBackoffTimeToWait( Job $job ) {
		global $wgJobBackoffThrottling;

		if ( !isset( $wgJobBackoffThrottling[$job->getType()] ) ||
			$job instanceof DuplicateJob // no work was done
		) {
			return 0; // not throttled
		}

		$itemsPerSecond = $wgJobBackoffThrottling[$job->getType()];
		if ( $itemsPerSecond <= 0 ) {
			return 0; // not throttled
		}

		$seconds = 0;
		if ( $job->workItemCount() > 0 ) {
			$exactSeconds = $job->workItemCount() / $itemsPerSecond;
			// use randomized rounding
			$seconds = floor( $exactSeconds );
			$remainder = $exactSeconds - $seconds;
			$seconds += ( mt_rand() / mt_getrandmax() < $remainder ) ? 1 : 0;
		}

		return (int)$seconds;
	}

	/**
	 * Get the previous backoff expiries from persistent storage
	 * On I/O or lock acquisition failure this returns the original $backoffs.
	 *
	 * @param array $backoffs Map of (job type => UNIX timestamp)
	 * @param string $mode Lock wait mode - "wait" or "nowait"
	 * @return array Map of (job type => backoff expiry timestamp)
	 */
	private function loadBackoffs( array $backoffs, $mode = 'wait' ) {
		$file = wfTempDir() . '/mw-runJobs-backoffs.json';
		if ( is_file( $file ) ) {
			$noblock = ( $mode === 'nowait' ) ? LOCK_NB : 0;
			$handle = fopen( $file, 'rb' );
			if ( !flock( $handle, LOCK_SH | $noblock ) ) {
				fclose( $handle );
				return $backoffs; // don't wait on lock
			}
			$content = stream_get_contents( $handle );
			flock( $handle, LOCK_UN );
			fclose( $handle );
			$ctime = microtime( true );
			$cBackoffs = json_decode( $content, true ) ?: [];
			foreach ( $cBackoffs as $type => $timestamp ) {
				if ( $timestamp < $ctime ) {
					unset( $cBackoffs[$type] );
				}
			}
		} else {
			$cBackoffs = [];
		}

		return $cBackoffs;
	}

	/**
	 * Merge the current backoff expiries from persistent storage
	 *
	 * The $deltas map is set to an empty array on success.
	 * On I/O or lock acquisition failure this returns the original $backoffs.
	 *
	 * @param array $backoffs Map of (job type => UNIX timestamp)
	 * @param array $deltas Map of (job type => seconds)
	 * @param string $mode Lock wait mode - "wait" or "nowait"
	 * @return array The new backoffs account for $backoffs and the latest file data
	 */
	private function syncBackoffDeltas( array $backoffs, array &$deltas, $mode = 'wait' ) {
		if ( !$deltas ) {
			return $this->loadBackoffs( $backoffs, $mode );
		}

		$noblock = ( $mode === 'nowait' ) ? LOCK_NB : 0;
		$file = wfTempDir() . '/mw-runJobs-backoffs.json';
		$handle = fopen( $file, 'wb+' );
		if ( !flock( $handle, LOCK_EX | $noblock ) ) {
			fclose( $handle );
			return $backoffs; // don't wait on lock
		}
		$ctime = microtime( true );
		$content = stream_get_contents( $handle );
		$cBackoffs = json_decode( $content, true ) ?: [];
		foreach ( $deltas as $type => $seconds ) {
			$cBackoffs[$type] = isset( $cBackoffs[$type] ) && $cBackoffs[$type] >= $ctime
				? $cBackoffs[$type] + $seconds
				: $ctime + $seconds;
		}
		foreach ( $cBackoffs as $type => $timestamp ) {
			if ( $timestamp < $ctime ) {
				unset( $cBackoffs[$type] );
			}
		}
		ftruncate( $handle, 0 );
		fwrite( $handle, json_encode( $cBackoffs ) );
		flock( $handle, LOCK_UN );
		fclose( $handle );

		$deltas = [];

		return $cBackoffs;
	}

	/**
	 * Make sure that this script is not too close to the memory usage limit.
	 * It is better to die in between jobs than OOM right in the middle of one.
	 * @return bool
	 */
	private function checkMemoryOK() {
		static $maxBytes = null;
		if ( $maxBytes === null ) {
			$m = [];
			if ( preg_match( '!^(\d+)(k|m|g|)$!i', ini_get( 'memory_limit' ), $m ) ) {
				list( , $num, $unit ) = $m;
				$conv = [ 'g' => 1073741824, 'm' => 1048576, 'k' => 1024, '' => 1 ];
				$maxBytes = $num * $conv[strtolower( $unit )];
			} else {
				$maxBytes = 0;
			}
		}
		$usedBytes = memory_get_usage();
		if ( $maxBytes && $usedBytes >= 0.95 * $maxBytes ) {
			$msg = "Detected excessive memory usage ($usedBytes/$maxBytes).";
			$this->debugCallback( $msg );
			$this->logger->error( $msg );

			return false;
		}

		return true;
	}

	/**
	 * Log the job message
	 * @param string $msg The message to log
	 */
	private function debugCallback( $msg ) {
		if ( $this->debug ) {
			call_user_func_array( $this->debug, [ wfTimestamp( TS_DB ) . " $msg\n" ] );
		}
	}

	/**
	 * Issue a commit on all masters who are currently in a transaction and have
	 * made changes to the database. It also supports sometimes waiting for the
	 * local wiki's slaves to catch up. See the documentation for
	 * $wgJobSerialCommitThreshold for more.
	 *
	 * @param Job $job
	 * @throws DBError
	 */
	private function commitMasterChanges( Job $job ) {
		global $wgJobSerialCommitThreshold;

		$lb = wfGetLB( wfWikiID() );
		if ( $wgJobSerialCommitThreshold !== false && $lb->getServerCount() > 1 ) {
			// Generally, there is one master connection to the local DB
			$dbwSerial = $lb->getAnyOpenConnection( $lb->getWriterIndex() );
		} else {
			$dbwSerial = false;
		}

		if ( !$dbwSerial
			|| !$dbwSerial->namedLocksEnqueue()
			|| $dbwSerial->pendingWriteQueryDuration() < $wgJobSerialCommitThreshold
		) {
			// Writes are all to foreign DBs, named locks don't form queues,
			// or $wgJobSerialCommitThreshold is not reached; commit changes now
			wfGetLBFactory()->commitMasterChanges( __METHOD__ );
			return;
		}

		$ms = intval( 1000 * $dbwSerial->pendingWriteQueryDuration() );
		$msg = $job->toString() . " COMMIT ENQUEUED [{$ms}ms of writes]";
		$this->logger->info( $msg );
		$this->debugCallback( $msg );

		// Wait for an exclusive lock to commit
		if ( !$dbwSerial->lock( 'jobrunner-serial-commit', __METHOD__, 30 ) ) {
			// This will trigger a rollback in the main loop
			throw new DBError( $dbwSerial, "Timed out waiting on commit queue." );
		}
		// Wait for the generic slave to catch up
		$pos = $lb->getMasterPos();
		if ( $pos ) {
			$lb->waitForOne( $pos );
		}

		$fname = __METHOD__;
		// Re-ping all masters with transactions. This throws DBError if some
		// connection died while waiting on locks/slaves, triggering a rollback.
		wfGetLBFactory()->forEachLB( function( LoadBalancer $lb ) use ( $fname ) {
			$lb->forEachOpenConnection( function( IDatabase $conn ) use ( $fname ) {
				if ( $conn->writesOrCallbacksPending() ) {
					$conn->query( "SELECT 1", $fname );
				}
			} );
		} );

		// Actually commit the DB master changes
		wfGetLBFactory()->commitMasterChanges( __METHOD__ );

		// Release the lock
		$dbwSerial->unlock( 'jobrunner-serial-commit', __METHOD__ );
	}
}


text:
package rapture.server.web.servlet;

import java.util.HashMap;
import java.util.Map;

/**
 * A class who's instances are used within a Reflex script for control
 *
 * @author amkimian
 *
 */
public class ResponseControl {
    public int getResponseCode() {
        return responseCode;
    }
    public void setResponseCode(int responseCode) {
        this.responseCode = responseCode;
    }
    public String getPageRedirection() {
        return pageRedirection;
    }
    public void setPageRedirection(String pageRedirection) {
        this.pageRedirection = pageRedirection;
    }
    public Map<String, ResponseCookie> getCookieMap() {
        return cookieMap;
    }
    public void setCookieMap(Map<String, ResponseCookie> cookieMap) {
        this.cookieMap = cookieMap;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    private int responseCode = 200;
    private String pageRedirection = null;
    private Map<String, ResponseCookie> cookieMap = new HashMap<String, ResponseCookie>();
    private String message = null;
}