text:
function [b,b1,w1,A,pv]=firdmm1(pp25,nw,nfreqs)

% Hamming-windowed lowpass filter design-- filtfilt version
% D. Meko 11-3-92
% See p. 2-58 in signal processing toolbox

% Design a low-pass filter and compute and plot
% its frequency response.  User specifies the 50% freq response
% for a filter b1.  Time series will be filtered with b1 forwards and
% then backwards.  This double filtering has effect of squaring the freq
% response, so that the effective filter is b=conv(b1,b1).
% So the final filter b will have a lower frequency response at pp25 than
% 0.5.  If the filter length is long enough,
% the period of the 25% response will approach pp25.

%********* OTHER USER-WRITTEN FUNCTIONS NEEDED
%
% respoint.m  - interpolates period of specified freq response
%
%
%********* INPUT ARGUMENTS
%
% pp25 (1 x 1) desired period in yrs of 50% freq response of filter
%  		b1, which will be convoluted with itself to get filter b
% nw (1 x 1) specified number of weights in filter, before convolution
%   The final filter will have 2* nw - 1 weights.
% nfreqs (1 x 1) number of frequency points between 0 and
%   0.5 per year that freq resp is to be returned for

%***********  OUTPUT ARGUMENTS
%
% b (1 x 2nw)  the filter weights convoluted withself
% b1 (1 x nw) the filter weights
% w1 (nfreqs x 1) frequencies (per year) for A
% A  (nfreqs x 1) frequency response
% pv (1x4) period (yr) of 90%, 50%, 25% and 10% freq response
%

n=nw-1;
Wn=2.0 / pp25;  % Cutoff frequency on scale such that 0 is
	% 0 per year, and Wn=1 is 0.5 per year (Nyquist).  At
	% this frequency, response of filter b1 is 0.5, and
	% response of b=conv(b1,b1) is 0.25 (if filter is broad
	% enough)

b1=fir1(n,Wn);

% Compute and plot magnitude frequency response

b=conv(b1,b1);
[h,w]=freqz(b,1,nfreqs);
A=abs(h) ; % Amplitude
%ph=phase(h');  % Phase
mn=ones(nfreqs,1) * 0.5;  % horiz line at fre resp of 1/2

w1=w / (2*pi);  % want freq in per year

p90=respoint(A,w1,0.9);
p50=respoint(A,w1,0.5);
p25=respoint(A,w1,0.25);
p10=respoints(A,w1,0.1);
pv=[p90 p50 p25 p10];

plot(w1,A,w1,mn); % plot magnitude response
title('MAGNITUDE OF FREQUENCY RESPONSE')
xlabel('Frequency (per year)')
ylabel('Response')
text(0.2,0.9,['Spec. Period of 25% Response = ',num2str(pp25),' yr']);
text(0.2,0.85,['Spec. Number of Weights = ',int2str(nw)]);
text(0.2,0.8,['90% Response: ',num2str(p90),' yr']);
text(0.2,0.75,['50% Response: ',num2str(p50),' yr']);
text(0.2,0.70,['25% Response: ',num2str(p25),' yr']);
text(0.2,0.65,['10% Response: ',num2str(p10),' yr']);

pause


text:
Name | Getter | Setter | Type | Description | Notes
------------ | ------------- | ------------- | ------------- | ------------- | -------------
**category** | getCategory() | setCategory($value) | **string** | The error's high-level category. See [ErrorCategory](#type-errorcategory) for possible values. |
**code** | getCode() | setCode($value) | **string** | The error's specific code. See [ErrorCode](#type-errorcode) for possible values |
**detail** | getDetail() | setDetail($value) | **string** | A human-readable description of the error for debugging purposes. | [optional]
**field** | getField() | setField($value) | **string** | The name of the field provided in the original request that the error pertains to, if any. | [optional]

Note: All properties are protected and only accessed via getters and setters.

[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)

redpajama_set_name: RedPajamaGithub


text:
namespace rl
{
	namespace hal
	{
		JointVelocitySensor::JointVelocitySensor(const ::std::size_t& dof) :
			AxisController(dof)
		{
		}

		JointVelocitySensor::~JointVelocitySensor()
		{
		}
	}
}


text:
package org.jboss.weld.tests.extensions.staticObserver;

import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessAnnotatedType;

/**
 * @author Antoine Sabot-Durand
 */
public class ExtensionWithStaticLifecycleEventObserver implements Extension {

    static void processAnnotatedType(@Observes ProcessAnnotatedType<?> pat) {

    }
}


text:
.. EN-Revision: none
.. _zend.gdata.introduction:

Einführung
==========

Die *API*\ s von Google Data bieten ein programmtechnisches Interface zu einigen von Google's Online Services. Das
Google Data Protokoll basiert auf dem `Atom Publishing Protokoll`_ und erlaubt Client Anwendungen das Empfangen von
passenden Anfragen zu Daten, senden von Daten, modifizieren von Daten und löschen von Daten wobei Standard *HTTP*
und das Atom Syndication Format verwendet wird. Die ``ZendGData`` Komponente ist ein *PHP* 5 Interface für den
Zugriff auf Daten von Google von *PHP* aus. Die ``ZendGData`` Komponente unterstützt auch den Zugriff auf andere
Services die das Atom Publishing Protokoll implementieren.

Siehe `http://code.google.com/apis/gdata/`_ für mehr Informationen über die Google Data *API*.

Die Services auf die durch ``ZendGData`` zugegriffen werden kann beinhalten unter anderem:

   - :ref:`Google Kalender <zend.gdata.calendar>` ist eine populäre online Kalender Anwendung.

   - :ref:`Google Tabellenkalkulation <zend.gdata.spreadsheets>` bietet ein gemeinschaftliches online
     Tabellenkalkulations Tool welches als einfacher Datenspeicher für eigene Anwendungen verwendet werden kann.

   - :ref:`Google Dokumenten Liste <zend.gdata.docs>` bietet eine online Liste von allen Tabellenkalkulationen,
     Wortbearbeitungs Dokumenten, und Präsentationen die in einem Google Account gespeichert sind.

   - :ref:`Google Versorgung <zend.gdata.gapps>` bietet die Möglichkeit Benutzerdaten, Spitznamen, Gruppen und
     Emaillisten auf einer Google Apps gehosten Domain zu erstellen, erhalten, aktualisieren und zu löschen.

   - :ref:`YouTube <zend.gdata.youtube>` bietet die Möglichkeit Videos, Kommentare, Favoriten, Einschreibungen,
     Benutzerprofile und vieles mehr zu Suchen und zu Empfangen.

   - :ref:`Picasa Web Album <zend.gdata.photos>` bietet eine online Photo Sharing Anwendung.

   - `Google Blogger`_ ist ein populärer Internet Provider von "push-button Veröffentlichung" und Verbreitung.

   - Google CodeSearch erlaubt das Suchen von öffentlichem Source Code für viele Projekte.

   - Google Notebook erlaubt das sehen von veröffentlichten Notebook Inhalten.

.. note::

   **Nicht unterstützte Services**

   ``ZendGData`` bietet kein Interface zu irgendwelchen anderen Google Services wie Search, Gmail, Translation
   oder Maps. Nur Services die das Google Data *API* unterstützen werden unterstützt.

.. _zend.gdata.introduction.structure:

Struktur von ZendGData
-----------------------

``Zend_Gata`` besteht aus verschiedenen Typen von Klassen:

   - Service Klassen - abgeleitet von ``ZendGData\App``. Diese beinhalten auch andere Klassen wie ``ZendGData``,
     ``ZendGData\Spreadsheeps``, usw. Diese Klassen erlauben die Interaktion mit APP oder GData Services und
     bieten die Möglichkeit Feeds und Einträge zu empfangen, Einträge zu senden, zu aktualisieren und zu
     löschen.

   - Abfrage Klassen - abgeleitet von ``ZendGData\Query``. Diese beinhalten auch andere Klassen für spezielle
     Services, wie ``ZendGData_Spreadsheet\ListQuery`` und ``ZendGData_Spreadsheets\CellQuery``. Abfrage Klassen
     bieten Methoden die verwendet werden können um Abfragen für Daten zu erstellen die von GData Services
     empfangen werden. Die Methoden inkludieren Getter und Setter wie ``setUpdatedMin()``, ``setStartIndex()``, und
     ``getPublishedMin()``. Die Abfrage Klassen haben auch eine Methode um eine *URL* zu erhalten welche die
     erstellte Abfrage repräsentieren. --``getQueryUrl()``. Alternativ kann man die Abfrage String Komponente der
     *URL* erhalten indem die ``getQueryString()`` Methode verwendet wird.

   - Feed Klassen - abgeleitet von ``ZendGData_App\Feed``. Diese beinhalten auch andere Klassen wie
     ``ZendGData\Feed``, ``ZendGData_Spreadsheets\SpreadsheetFeed``, und ``ZendGData_Spreadsheets\ListFeed``.
     Diese Klassen repräsentieren Feeds von Einträgen die von Services empfangen wurden. Sie werden primär
     verwendet um Daten die von Services zurückgegeben werden zu erhalten.

   - Eingabe Klassen - abgeleitet von ``ZendGData_App\Entry``. Diese beinhalten auch andere Klassen wie
     ``ZendGData\Entry``, und ``ZendGData_Spreadsheets\ListEntry``. Diese Klassen repräsentieren Einträge die
     von Services empfangen oder für die Erstellung von Daten, die an Services geschickt werden, verwendet werden.
     Zusätzlich zur Möglichkeit die Eigenschaften eines Eintrages (wie den Zellen Wert der Tabellenkalkulation)
     zu setzen, kann das Objekt des Eintrages verwendet werden um Aktualisierungs- oder Löschanfragen an ein
     Service zu senden. Zum Beispiel kann ``$entry->save()`` aufgerufen werden um Änderungen die an einem Eintrage
     durchgeführt wurden zu einem Service zurück zu Speichern von welche der Eintrag initiiert wurde, oder
     ``$entry->delete()`` um einen Eintrag von einem Server zu Löschen.

   - Andere Daten Modell Klassen - abgeleitet von ``ZendGData_App\Extension``. Diese beinhalten Klassen wie
     ``ZendGData\App\Extension\Title`` (repräsentiert das atom:title *XML* Element),
     ``ZendGData_Extension\When`` (repräsentiert das gd:when *XML* Element das von dem GData Event "Kind"
     verwendet wird), und ``ZendGData_Extension\Cell`` (repräsentiert das gs:cell *XML* Element das von Google
     Tabellenkalkulation verwendet wird). Diese Klassen werden pur verwendet um von den Server zurückgegebene
     Daten zu speichern und für die Erstellung von Daten die an Services gesendet werden. Diese beinhalten Getter
     und Setter wie ``setText()`` um den Kindtext Node eines Elements zu setzen, ``getText()`` um den Text Node
     eines Elements zu erhalten, ``getStartTime()`` um das Startzeit Attribut eines When Elements oder anderen
     ähnlichen Methoden zu empfangen. Die Daten Modell Klassen beinhalten auch Methoden wie ``getDOM()`` um eine
     DOM Repräsentation des Elements und aller Kinder zu erhalten, und ``transferFromDOM()`` um eine Daten Modell
     Repräsentation des DOM Baumes zu erstellen.

.. _zend.gdata.introduction.services:

Mit Google Services interagieren
--------------------------------

Google Daten Services basieren auf dem Atom Publishing Protokoll (APP) und dem Atom Syndication Format. Um mit APP
oder den Google Services zu interagieren indem ``ZendGData`` verwendet wird, müssen Service Klassen wie
``ZendGData\App``, ``ZendGData``, ``ZendGData\Spreadsheets``, usw. verwendet werden. Diese Service Klassen
bieten Methoden um Daten von Services als Feeds zu empfangen, neue Einträge in Feeds einzufügen, Einträge zu
aktuslieieren und Einträge zu löschen.

Achtung: Ein komplettes Beispiel davon wie mit ``ZendGData`` gearbeitet werden kann ist im ``demos/Zend/Gdata``
Verzeichnis vorhanden. Dieses Beispiel läuft von der Kommandozeile aus, aber die enthaltenen Methoden sind einfach
in einem Web Anwendung zu portieren.

.. _zend.gdata.introduction.magicfactory:

Instanzen von ZendGData Klassen erhalten
-----------------------------------------

Der Zend Framework Namensstandard erzwingt das alle Klassen nach der Verzeichnis Struktur benannt werden in welcher
sie vorhanden sind. Zum Beispiel eine Erweiterung die zu Tabellenkalkulation gehört und in
``Zend/Gdata/Spreadsheets/Extension/...`` gespeichert ist, muß als Ergebnis
``ZendGData\Spreadsheets\Extension\...`` benannt werden. Das verursacht eine Menge an Tipparbeit wenn versucht
wird eine neue Instanz eines Zellen Elements zu erstellen!

Wir haben eine magische Fabriksmethode in alle Service Klassen (wie ``ZendGData\App``, ``ZendGData``,
``ZendGData\Spreadsheets``) implementiert welche die Erstellung neuer Instanzen von Daten Modellen, Abfragen und
anderen Klassen viel einfacher macht. Diese magische Fabriksmethode ist durch die Verwendung der magischen
``__call()`` Methode implementiert um auf alle Versuche ``$service->newXXX(arg1, arg2, ...)`` aufzurufen,
angewendet zu werden. Basieren auf dem Wert von XXX, wird eine Suche in allen registrierten 'Paketen', für die
gewünschte Klasse, durchgeführt. Hier sind einige Beispiele:

.. code-block:: php
   :linenos:

   $ss = new ZendGData\Spreadsheets();

   // Erstellt ein ZendGData\App\Spreadsheets\CellEntry
   $entry = $ss->newCellEntry();

   // Erstellt ein ZendGData\App\Spreadsheets\Extension\Cell
   $cell = $ss->newCell();
   $cell->setText('Mein Zellenwert');
   $cell->setRow('1');
   $cell->setColumn('3');
   $entry->cell = $cell;

   // ... $entry kann dann verwendet werden um eine Aktualisierung
   // an eine Google Tabellenkalkulation zu senden

Jede Service Klasse im abgeleiteten Baum ist dafür verantwortlich das die richtigen 'Pakete' (Verzeichnisse)
registriert werden, in welchen dann durch den Aufruf der matischen Fabriksmethode, gesucht wird.

.. _zend.gdata.introduction.authentication:

Google Data Client Authentifizierung
------------------------------------

Die meisten Google Daten Services erfordern das sich die Client Anwendung auf dem Google Server authentifiziert
bevor auf private Daten zugegriffen, oder Daten gespeichert oder gelöscht werden können. Es gibt zwei
Implementationen der Authentifizierung für Google Daten: :ref:`AuthSub <zend.gdata.authsub>` und :ref:`ClientLogin
<zend.gdata.clientlogin>`. ``ZendGData`` bietet Klassen Interfaces für beide dieser Methoden.

Die meisten anderen Typen von Abfragen auf Google Daten Servicen benötigen keine Authentifizierung.

.. _zend.gdata.introduction.dependencies:

Abhängigkeiten
--------------

``ZendGData`` verwendet :ref:`Zend\Http\Client <zend.http.client>` um Anfragen an google.com zu senden und
Ergebnisse zu erhalten. Die Antworter der meisten Google Data Anfragen werden als Subklasse von
``ZendGData_App\Feed`` oder ``ZendGData_App\Entry`` Klassen zurückgegeben.

``ZendGData`` nimmt an das die *PHP* Anwendung auf einem Host läuft der eine direkte Verbindung zum Internet hat.
Der ``ZendGData`` Client arbeitet indem er zu Google Daten Servern Kontakt aufnimmt.

.. _zend.gdata.introduction.creation:

Erstellen eines neuen Gdata Klienten
------------------------------------

Man muß ein neues Objekt der Klasse ``ZendGData\App``, ``ZendGData``, oder einer dessen Subklassen erstellen die
Helfer Methoden für servicespezifische Verhaltensweisen anbieten.

Der einzige optionale Parameter für den Konstruktor von ``ZendGData\App`` ist eine Instanz von
:ref:`Zend\Http\Client <zend.http.client>`. Wenn dieser Parameter nicht übergeben wird, erstellt ``ZendGData``
ein standardmäßiges ``Zend\Http\Client`` Objekt, welches keine Zugangsdaten zugeordnet hat um auf private Feeds
zugreifen zu können. Die Spezifizierung des ``Zend\Http\Client`` Objektes erlaubt es auch Konfigurationsoptionen
an das Client Objekt zu übergeben.

.. code-block:: php
   :linenos:

   $client = new Zend\Http\Client();
   $client->setConfig( ...options... );

   $gdata = new ZendGData\Gdata($client);

Beginnend mit Zend Framework 1.7, wurde die Unterstützung für die Versionierung des Protkolls hinzugefügt. Das
erlaut dem Client und Server neue Fesatures zu unterstützen, wärend die Rückwärts Kompatibilität gewahrt
bleibt. Wärend die meisten Services das für dich selbst durchführen, wenn man eine ``ZendGData`` Instanz direkt
erstellt (als Gegensatz zu einer Ihrer Unterklassen), kann es sein das man die gewünschte Version des Protokolls
spezifizieren will um auf spezielle Serverfunktionalitäten zugreifen zu können.

.. code-block:: php
   :linenos:

   $client = new Zend\Http\Client();
   $client->setConfig( ...options... );

   $gdata = new ZendGData\Gdata($client);
   $gdata->setMajorProtocolVersion(2);
   $gdata->setMinorProtocolVersion(null);

Siehe auch die Sektion über Authentifizierung für Methoden, um ein authentifiziertes ``Zend\Http\Client`` Objekt
zu erstellen.

.. _zend.gdata.introduction.parameters:

Übliche Abfrage Parameter
-------------------------

Es können Parameter spezifiziert werden um Abfragen mit ``ZendGData`` anzupassen. Abfrageparameter werden
spezifiziert indem Subklassen von ``ZendGData\Query`` verwendet werden. Die ``ZendGData\Query`` Klasse beinhaltet
Methoden um alle Abfrageparameter zu setzen die von Gdata Services verwendet werden. Individuelle Services, wie
Tabellenkalkulationen, bieten auch Abfrageklassen zu definierten Parametern welche an das spezielle Service und die
Feeds angepasst sind. Tabellenkalkulationen beinhalten eine CellQuery Klasse um den Zellen Feed abzufragen und eine
ListQuery Klasse um den Listen Feed abzufragen, da verschiedene Abfrageparameter für jeder dieser Feedtypen
möglich sind. Die GData-weiten Parameter werden anbei beschrieben.

- Der ``q`` Parameter spezifiziert eine komplette Textabfrage. Der Wert dieses Parameters ist ein String.

  Dieser Parameter kann mit der ``setQuery()`` Methode gesetzt werden.

- Der ``alt`` Parameter spezifiziert den Feed Typ. Der Wert dieses Parameters kann ``atom``, ``rss``, ``json``,
  oder ``json-in-script`` sein. Wenn dieser Parameter nicht spezifiziert wird, ist der Standard Feedtyp ``atom``.
  ``Zend\Http\Client`` könnte verwendet werden um Feeds in anderen Formaten zu empfangen, indem die von der
  ``ZendGData\Query`` Klasse oder deren Subklassen erzeugten Abfrage *URL*\ s verwendet werden.

  Dieser Parameter kann mit der ``setAlt()`` Methode gesetzt werden.

- Der ``maxResults`` Parameter begrenzt die Anzahl an Einträgen im Feed. Der Wert dieses Parameters ist ein
  Integer. Die zurückgegebene Anzahl an Einträgen im Feed wird diesen Wert nicht überschreiten.

  Dieser Parameter kann mit der ``setMaxResults()`` Methode gesetzt werden.

- Der ``startIndex`` Parameter spezifiziert die ordinale Nummer des ersten Eintrags der im Feed zurückgegeben
  wird. Einträge vor dieser Nummer werden übergangen.

  Dieser Parameter kann mit der ``setStartIndex()`` Methode gesetzt werden.

- Die Parameter ``updatedMin`` und ``updatedMax`` spezifizieren Grenzen für das Datum der Einträge. Wenn ein Wert
  für ``updatedMin`` spezifiziert wird, werden keine Einträge die vor dem spezifizierten Datum aktualisiert
  wurden, im Feed inkludiert. Genauso werden keine Einträge inkludiert die nach einem Datum aktualisiert wurden
  wenn ``updatedMax`` spezifiziert wird.

  Es können nummerische Zeitstempel, oder eine Variation von Datum/Zeit String Repräsentationen als Wert für
  diese Parameter verwendet werden.

  Diese Parameter kkönnen mit den ``setUpdatedMin()`` und ``setUpdatedMax()`` Methoden gesetzt werden.

Es gibt eine ``get*()`` Funktion für jede ``set*()`` Funktion.

.. code-block:: php
   :linenos:

   $query = new ZendGData\Query();
   $query->setMaxResults(10);
   echo $query->getMaxResults();   // gibt 10 zurück

Die ``ZendGData`` Klasse implementiert auch "magische" Getter und Setter Methoden, es kann also der Name des
Parameters als virtuelles Mitglied der Klasse verwendet werden.

.. code-block:: php
   :linenos:

   $query = new ZendGData\Query();
   $query->maxResults = 10;
   echo $query->maxResults;        // gibt 10 zurück

Es können alle Parameter mit der ``resetParameters()`` Funktion gelöscht werden. Das ist nützlich wenn ein
``ZendGData`` Objekt für mehrfache Abfragen wiederverwendet werden soll.

.. code-block:: php
   :linenos:

   $query = new ZendGData\Query();
   $query->maxResults = 10;
   // ...den Feed empfangen...

   $query->resetParameters();      // löscht alle Parameter
   // ...einen anderen Feed empfangen...

.. _zend.gdata.introduction.getfeed:

Einen Feed empfangen
--------------------

Die ``getFeed()`` Funktion kann verwendet werden um einen Feed von einer spezifizierten *URI* zu empfangen. Diese
Funktion gibt eine Instanz der Klasse, die als zweites Argument an getFeed übergeben wurde, zurück, welche
standardmäßig ZendGData\Feed ist.

.. code-block:: php
   :linenos:

   $gdata = new ZendGData\Gdata();
   $query = new ZendGData\Query(
           'http://www.blogger.com/feeds/blogID/posts/default');
   $query->setMaxResults(10);
   $feed = $gdata->getFeed($query);

Siehe spätere Sektionen für spezielle Funktionen in jeder Helfer Klasse für Google Daten Services. Diese
Funktionen helfen Feeds von einer *URI* zu empfangen die für das angeforderte Service zuständig ist.

.. _zend.gdata.introduction.paging:

Mit Mehrfach-Seiten Feeds arbeiten
----------------------------------

Wenn man einen Feed empfängt der eine große Anzahl an Einträgen enthält, kann dieser Feed in viele kleinere
"Seiten" von Feeds gebrochen werden. Wenn das passiert, enthält jede Seite einen Link zur nächsten Seite der
Serie. Auf diesen Link kann mit Hilfe von ``getLink('next')`` zugegriffen werden. Das folgende Beispiel zeigt wie
auf die nächste Seite eines Feeds empfangen werden kann:

.. code-block:: php
   :linenos:

   function getNextPage($feed) {
       $nextURL = $feed->getLink('next');
       if ($nextURL !== null) {
           return $gdata->getFeed($nextURL);
       } else {
           return null;
       }
   }

Wenn man es vorzieht nicht mit Seiten in der eigenen Anwendung zu arbeiten, kann die erste Seite des Feeds an
``ZendGData\App::retrieveAllEntriesForFeed()`` übergeben werden, welche alle Einträge von jeder Seite in einen
einzelnen Feed zusammenfasst. Dieses Beispiel zeigt wie diese Funktion verwendet werden kann:

.. code-block:: php
   :linenos:

   $gdata = new ZendGData\Gdata();
   $query = new ZendGData\Query(
           'http://www.blogger.com/feeds/blogID/posts/default');
   $feed = $gdata->retrieveAllEntriesForFeed($gdata->getFeed($query));

Es gilt zu beachten das wenn diese Funktion aufgerufen wird, dies eine sehr lange Zeit benötigen kann im große
Feeds zu komplettieren. Es kann notwendig sein *PHP*'s Limit der Ausführungszeit zu vergrößern mithilfe von
``set_time_limit()`` zu vergrößern.

.. _zend.gdata.introduction.usefeedentry:

Arbeiten mit Daten in Feeds und Einträgen
-----------------------------------------

Nachdem ein Feed empfangen wurde, können die Daten von dem Feed oder den Einträgen die in dem Feed enthalten
sind, gelesen werden, indem entweder die in jeder Daten Modell Klasse definierten Zugriffsmethoden oder die
magischen Zugriffsmethoden verwendet werden. Hier ist ein Beispiel:

.. code-block:: php
   :linenos:

   $client = ZendGData\ClientLogin::getHttpClient($user, $pass, $service);
   $gdata = new ZendGData\Gdata($client);
   $query = new ZendGData\Query(
           'http://www.blogger.com/feeds/blogID/posts/default');
   $query->setMaxResults(10);
   $feed = $gdata->getFeed($query);
   foreach ($feed as $entry) {
       // Die magischen Zugriffsmethoden verwenden
       echo 'Titel: ' . $entry->title->text;
       // Die definierten Zugriffsmethoden verwenden
       echo 'Inhalt: ' . $entry->getContent()->getText();
   }

.. _zend.gdata.introduction.updateentry:

Einträge aktualisieren
----------------------

Nachdem ein Eintrag empfangen wurde, kann dieser Eintrag aktualisiert und die Änderungen an den Server zurück
gespeichert werden. Hier ist ein Beispiel:

.. code-block:: php
   :linenos:

   $client = ZendGData\ClientLogin::getHttpClient($user, $pass, $service);
   $gdata = new ZendGData\Gdata($client);
   $query = new ZendGData\Query(
           'http://www.blogger.com/feeds/blogID/posts/default');
   $query->setMaxResults(10);
   $feed = $gdata->getFeed($query);
   foreach ($feed as $entry) {
       // Dem Titel 'NEU' hinzufügen
       echo 'Alter Titel: ' . $entry->title->text;
       $entry->title->text = $entry->title->text . ' NEU';

       // Den Eintrag auf dem Server aktualisieren
       $newEntry = $entry->save();
       echo 'New Title: ' . $newEntry->title->text;
   }

.. _zend.gdata.introduction.post:

Einträge an Google Server schicken
----------------------------------

Das ``ZendGData`` Objekt hat eine ``insertEntry()`` Funktion mit der man Daten hochladen kann um neue Einträge in
Google Data Services zu speichern.

Die Daten Modell Klassen jedes Services kann verwendet werden um einen entsprechenden Eintrag zu erstellen und an
Google's Services zu schicken. Die ``insertEntry()`` Funktion akzeptiert ein Kind von ``ZendGData_App\Entry`` als
Daten die an den Service geschickt werden. Die Methode gibt ein Kind von ``ZendGData_App\Entry`` zurück welches
den Status des Eintrages repräsentiert der vom Server zurückgegeben wurde.

Alternativ, kann die *XML* Struktur eines Eintrages als String konstruiert und dieser String an die
``insertEntry()`` Funktion übergeben werden.

.. code-block:: php
   :linenos:

   $gdata = new ZendGData\Gdata($authenticatedHttpClient);

   $entry = $gdata->newEntry();
   $entry->title = $gdata->newTitle('Füßball im Park spielen');
   $content =
       $gdata->newContent('Wir besuchen den Part und spielen Fußball');
   $content->setType('text');
   $entry->content = $content;

   $entryResult = $gdata->insertEntry($entry,
           'http://www.blogger.com/feeds/blogID/posts/default');

   echo 'Die <id> des resultierenden Eintrages ist: ' . $entryResult->id->text;

Um Einträge zu senden, muß ein authentifizierter ``Zend\Http\Client`` verwendet werden der mit Hilfe der
``ZendGData\AuthSub`` oder ``ZendGData\ClientLogin`` Klassen erstellt wurde.

.. _zend.gdata.introduction.delete:

Einträge auf einem Google Server löschen
----------------------------------------

Option 1: Das ``ZendGData`` Objekt hat eine ``delete()`` Funktion mit der Einträge von Google Daten Services
gelöscht werden können. Der bearbeitete *URL* Wert eines Feed Eintrages kann der ``delete()`` Methode übergeben
werden.

Option 2: Alternativ kann ``$entry->delete()`` an einem Eintrag der von einem Google Service empfangen wurde,
aufgerufen werden.

.. code-block:: php
   :linenos:

   $gdata = new ZendGData\Gdata($authenticatedHttpClient);
   // ein Google Daten Feed
   $feedUri = ...;
   $feed = $gdata->getFeed($feedUri);
   foreach ($feed as $feedEntry) {
       // Option 1 - den Eintrag direkt löschen
       $feedEntry->delete();
       // Option 2 - den eintrag durch Übergabe der bearbeiteten URL an
       // $gdata->delete() löschen
       // $gdata->delete($feedEntry->getEditLink()->href);
   }

Um Einträge zu löschen, muß ein authentifizierter ``Zend\Http\Client`` verwendet werden der mit Hilfe der
``ZendGData\AuthSub`` oder ``ZendGData\ClientLogin`` Klassen erstellt wurde.

.. _`Atom Publishing Protokoll`: http://ietfreport.isoc.org/idref/draft-ietf-atompub-protocol/
.. _`http://code.google.com/apis/gdata/`: http://code.google.com/apis/gdata/
.. _`Google Blogger`: http://code.google.com/apis/blogger/developers_guide_php.html


text:
layout: post
author: adam
title: Repository Pattern: Properly Organizing Your Data Layer
description: An explanation of the repository pattern and why we need it.
modified: 2019-05-20
published: true
tags: [architecture]
categories: [android]
---

How to properly architect your application is a concern we as developers constantly face. There's unfortunately no one size fits all answer to it, and sometimes we don't even know where to begin. I've learned along my Android journey that the answer can also vary depending on what portion of your app you're trying to organize. Of course, you might say, [it depends](https://handstandsam.com/2019/03/10/it-depends-is-the-answer-to-your-android-question/).

When it comes to your data layer, though, there are some really good tips on how to write clean, maintainable code. One of them is the Repository Pattern, and I'd like to provide a quick walk through of what it is and why it's important.

<!--more-->

# TL;DR

The repository pattern is a way to organize your code such that your ViewModel or Presenter class doesn't need to care about where your data comes from. It only cares about how to request data and what it gets back.

# A Bad Example

Let's first look at what happens to our code when we _don't_ implement the repository pattern. Let's say I have a detail page for a Pokemon (yes, I love using Pokemon examples), and I want to fetch the data from a retrofit service. I might end up with a ViewModel looking something like this:

```kotlin
class DetailActivityViewModel(
    private val pokemonAPI: PokemonAPI
) : BaseObservableViewModel() {
    ...

    init {
        job = CoroutineScope(dispatcherProvider.IO).launch {
            ...

            val pokemon = pokemonAPI.getPokemonDetailAsync(pokemonName).await()

            ...
        }
    }

    ...
}
```

While this may not look awful, it actually poses an interesting limitation. What if you were asked to fetch from a GraphQL API instead? Or even a local database? What if you wanted a mix, or to A/B test multiple approaches?

Depending on which one of those you chose, this gets really ugly. First and foremost, you'd have to add the relevant properties to your ViewModel, and then your ViewModel class eventually becomes bloated with data layer work that really doesn't belong there anymore.

If you've ever found yourself in this spot, even if you haven't yet hit this limitation (some people only use a Retrofit API and that's fine), you may want to consider helping your future self with the repository pattern.

# Repository Interface

Going back up to the TL;DR, your ViewModel shouldn't care where the information comes from. In many programming problems where we don't care about the implementation of something, we can put the contract of what we do care about in an interface.

We can start there by defining our interface for what our data fetching behavior should be:

```kotlin
interface PokemonRepository {
    suspend fun getPokemon(): PokemonResponse
    suspend fun getPokemonDetail(pokemonName: String): Pokemon
}
```

Once we've defined that, we should update our ViewModel to use this interface:

```kotlin
class DetailActivityViewModel(
    private val repository: PokemonRepository
) : BaseObservableViewModel() {
    ...

    init {
        job = CoroutineScope(dispatcherProvider.IO).launch {
            ...

            val pokemon = repository.getPokemonDetail(pokemonName)

            ...
        }
    }

    ...
}
```

Now we're in a good place to take control of where our data comes from, and update it as needed without worrying about updating our ViewModel.

# The Implementation

If you were someone who was only using one data source, like a Retrofit API, you only have to worry about creating one implementation, which can be done with some heavy copy and paste. In the Pokedex example, we converted our implementation to this:

```kotlin
open class PokemonRetrofitService(
    private val api: PokemonAPI
): PokemonRepository {
    override suspend fun getPokemon(): PokemonResponse {
        return api.getPokemonAsync().await()
    }

    override suspend fun getPokemonDetail(pokemonName: String): Pokemon {
        return api.getPokemonDetailAsync(pokemonName).await()
    }
}
```

Now, we can just update our call site for creating the ViewModel to use this implementation:

```kotlin
private val viewModelFactory = object : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val pokemonAPI = ...
        val repository = PokemonRetrofitService(pokemonAPI)

        return DetailActivityViewModel(repository) as T
    }
}
```

# Multiple Implementation Example

This pattern is especially important if you want to consider multiple implementations for fetching data. A common example may be that you want to also fetch data from a local database, in addition to your network service.

Let's consider an example where we have an explicit offline mode that fetches data from a database. If your code is already using the repository pattern, we don't need to worry about updating the ViewModel.

All we would need to do is create our `DatabasePokemonService` and then we can conditionally pass that into the ViewModel:

```kotlin
private val viewModelFactory = object : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val repository = getPokemonRepository()

        return DetailActivityViewModel(repository) as T
    }
}

private fun getPokemonRepository(): PokemonRepository {
    if (offlineMode()) {
        return DatabasePokemonService()
    } else {
        return RetrofitPokemonService()
    }
}
```

# Testing Benefits

When you move your data fetching code into an interface, you also make unit testing a lot easier! Our unit tests for the ViewModel don't have to worry about the data implementation either, we can just use Mockito to mock the interface and stub test data that way:

```kotlin
class DetailActivityViewModelTest {
    ...

    private val mockRepository = mock(PokemonRepository::class.java)

    @Test
    fun loadData() {
        val testPokemon = Pokemon(name = "Adam", types = listOf(TypeSlot(type = Type("grass"))))

        whenever(mockRepository.getPokemonDetail(anyString())).thenReturn(testPokemon)

        ...
    }

    ...
}
```

Now we don't have to worry about creating a room database in our unit tests, or a retrofit service. Dealing with an interface can help avoid all of those struggles.

# Resources

I hope you found this helpful in understanding how to properly organize your data fetching code. If you want to see the repository pattern in action (although I don't do this A/B testing scenario), you should check out this [Pokedex project](https://github.com/AdamMc331/PokeDex) on GitHub.

If you like analyzing the code directly, you can see the repository pattern implemented in [this pull request](https://github.com/AdamMc331/PokeDex/pull/20).


text:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
		<shape xmlns:android="http://schemas.android.com/apk/res/android">
		    <stroke android:width="4dp" android:color="#666" />
		    <solid android:color="#000000" />

		    <corners android:radius="0dp" />
		</shape>
   </item>

   <item android:top="4dp" android:bottom="4dp" android:right="4dp">
      <shape
        android:shape="rectangle">
            <solid android:color="#000000" />
        </shape>
   </item>

</layer-list>


text:
<?php

return array(

	/*
	|--------------------------------------------------------------------------
	| PDO Fetch Style
	|--------------------------------------------------------------------------
	|
	| By default, database results will be returned as instances of the PHP
	| stdClass object; however, you may desire to retrieve records in an
	| array format for simplicity. Here you can tweak the fetch style.
	|
	*/

	'fetch' => PDO::FETCH_CLASS,

	/*
	|--------------------------------------------------------------------------
	| Default Database Connection Name
	|--------------------------------------------------------------------------
	|
	| Here you may specify which of the database connections below you wish
	| to use as your default connection for all database work. Of course
	| you may use many connections at once using the Database library.
	|
	*/

	'default' => 'pgsql',

	/*
	|--------------------------------------------------------------------------
	| Database Connections
	|--------------------------------------------------------------------------
	|
	| Here are each of the database connections setup for your application.
	| Of course, examples of configuring each database platform that is
	| supported by Laravel is shown below to make development simple.
	|
	|
	| All database work in Laravel is done through the PHP PDO facilities
	| so make sure you have the driver for your particular database of
	| choice installed on your machine before you begin development.
	|
	*/

	'connections' => array(

		'sqlite' => array(
			'driver'   => 'sqlite',
			'database' => __DIR__.'/../database/production.sqlite',
			'prefix'   => '',
		),

		'mysql' => array(
			'driver'    => 'mysql',
			'host'      => 'localhost',
			'database'  => 'forge',
			'username'  => 'forge',
			'password'  => '',
			'charset'   => 'utf8',
			'collation' => 'utf8_unicode_ci',
			'prefix'    => '',
		),

		//server connection info
		    'openshift' => array(
		    'driver'   => 'pgsql',
		    'host'     => getenv('OPENSHIFT_POSTGRESQL_DB_HOST'),
		    'database' => 'freetime',
		    'username' => 'admincq2da2u',
		    'password' => 'Yh188i1B5DXr',
		    'charset'  => 'utf8',
		    'prefix'   => '',
		    'schema'   => 'public',
            'port'     => getenv('OPENSHIFT_POSTGRESQL_DB_PORT'),
		),

		'pgsql' => array(
			'driver'   => 'pgsql',
			'host'     => 'localhost',
			'database' => 'freetime',
			'username' => 'freetime',
			'password' => 'freetime',
			'charset'  => 'utf8',
			'prefix'   => '',
			'schema'   => 'public',
		),

		'sqlsrv' => array(
			'driver'   => 'sqlsrv',
			'host'     => 'localhost',
			'database' => 'database',
			'username' => 'root',
			'password' => '',
			'prefix'   => '',
		),

	),

	/*
	|--------------------------------------------------------------------------
	| Migration Repository Table
	|--------------------------------------------------------------------------
	|
	| This table keeps track of all the migrations that have already run for
	| your application. Using this information, we can determine which of
	| the migrations on disk haven't actually been run in the database.
	|
	*/

	'migrations' => 'migrations',

	/*
	|--------------------------------------------------------------------------
	| Redis Databases
	|--------------------------------------------------------------------------
	|
	| Redis is an open source, fast, and advanced key-value store that also
	| provides a richer set of commands than a typical key-value systems
	| such as APC or Memcached. Laravel makes it easy to dig right in.
	|
	*/

	'redis' => array(

		'cluster' => false,

		'default' => array(
			'host'     => '127.0.0.1',
			'port'     => 6379,
			'database' => 0,
		),

	),

);


text:
std::vector<Point> Block::pointsToAbsolute(std::vector<Point> points)
{
	std::vector<Point> result;

	for (unsigned int i = 0; i < points.size(); i++) {
		result.push_back(Point(points[i].x + position.x, points[i].y + position.y));
	}

	return result;
}

std::vector<Point> Block::getRelativePoints(int rotation)
{
	std::vector<Point> result = getRelativePoints();

	for (int n = 0; n < rotation; n++) {
		for (unsigned int i = 0; i < result.size(); i++) {
			int newX = -result[i].y;
			int newY = result[i].x;
			result[i].x = newX;
			result[i].y = newY;
		}
	}

	return result;
}

std::vector<Point> Block::getPoints()
{
	return pointsToAbsolute(getRelativePoints(currentRotation));
}

std::vector<Point> Block::getPoints(int rotation)
{
	return pointsToAbsolute(getRelativePoints(rotation));
}

bool Block::hasPoint(Point point)
{
	std::vector<Point> points = getPoints();

	for (unsigned int i = 0; i < points.size(); i++) {
		if (points[i].x == point.x && points[i].y == point.y) {
			return true;
		}
	}

	return false;
}


text:
package gwt.material.design.chat.client.local.widget;

import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.ui.Composite;
import gwt.material.design.addins.client.sideprofile.MaterialSideProfile;
import gwt.material.design.chat.client.avatar.MaterialAvatar;
import gwt.material.design.chat.client.local.events.SetCurrentUserEvent;
import gwt.material.design.client.constants.IconType;
import gwt.material.design.client.constants.SideNavType;
import gwt.material.design.client.ui.MaterialLabel;
import gwt.material.design.client.ui.MaterialLink;
import gwt.material.design.client.ui.MaterialSideNav;
import gwt.material.design.client.ui.MaterialToast;
import org.jboss.errai.ui.shared.api.annotations.DataField;
import org.jboss.errai.ui.shared.api.annotations.Templated;

import javax.annotation.PostConstruct;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

/**
 * Created by Mark Kevin on 6/8/2016.
 */
@Templated("SideNav.html#container")
public class SideNav extends Composite {

    @Inject
    @DataField
    MaterialSideNav sideNav;

    @Inject
    MaterialSideProfile sideProfile;

    @Inject
    MaterialAvatar image;

    @Inject
    MaterialLabel name;

    @Inject
    MaterialLabel id;

    @Inject
    MaterialLink linkRoom;

    @Inject
    MaterialLink linkSettings;

    @PostConstruct
    public void init() {
        sideNav.setId("sideNav");
        sideNav.setType(SideNavType.FIXED);
        sideNav.setWidth(280);
        sideNav.reinitialize();

        sideProfile.setUrl("https://graphicflip.com/wp-content/uploads/2016/02/40-backgrounds-material.jpg");
        sideNav.add(sideProfile);
    }

    public void onSetCurrentEvent(@Observes SetCurrentUserEvent event) {
        image.setName(event.getUser().getUniqueId());
        name.setText(event.getUser().getUsername());
        id.setText(event.getUser().getUniqueId());

        image.setCircle(true);
        image.setBackgroundColor("white");
        image.setShadow(2);
        image.setWidth("80");
        image.setHeight("80");
        sideProfile.add(image);

        name.setFontSize(1.2, Style.Unit.EM);
        name.setTextColor("white");
        sideProfile.add(name);

        id.setTextColor("white");
        id.setFontSize(0.8, Style.Unit.EM);
        id.setMarginTop(24);
        id.setOpacity(0.6);
        sideProfile.add(id);

        linkRoom.setText("Room");
        linkRoom.setIconType(IconType.MESSAGE);
        linkRoom.setHref("#chat");
        sideNav.add(linkRoom);

        linkSettings.setText("Settings");
        linkSettings.setIconType(IconType.SETTINGS);
        linkSettings.setHref("#settings");
        sideNav.add(linkSettings);
    }

}


text:
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>edu.usc</groupId>
        <artifactId>goffish</artifactId>
        <version>2.6</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>
    <groupId>edu.usc.goffish.gopher</groupId>
    <artifactId>samples</artifactId>
    <version>2.6</version>
    <packaging>pom</packaging>

    <name>Gopher samples</name>
    <url>http://maven.apache.org</url>

    <profiles>
        <profile>
            <id>release</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <attach>true</attach>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
            <activation>
                <property>
                    <name>release</name>
                </property>
            </activation>
        </profile>
    </profiles>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>edu.usc.goffish.gopher</groupId>
                <artifactId>gopher-api</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>edu.usc.goffish.gopher</groupId>
                <artifactId>gopher-core</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>MavenCentral</id>
            <name>Maven repository</name>
            <url>http://repo1.maven.org/maven2</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>

        <repository>
            <id>Codehaus Snapshots</id>
            <url>http://snapshots.repository.codehaus.org/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>

    <modules>
        <!-- Include the new modules -->
        <module>connected-components</module>
        <module>vertex-count</module>
        <module>page-rank</module>
        <module>shortest-path</module>
        <module>blockrank</module>
        <module>lpr</module>
        <module>N_HOP_STATS</module>
        <module>timedependent-shortestpath</module>
        <module>hash-count</module>
        <module>meme-propagation</module>
    </modules>

    <properties>
        <!-- Sets the source encoding to UTF-8 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- Maven Tools -->
        <maven.version>3.0.4</maven.version>
    </properties>

    <developers>
        <!-- If you are a committer and your name is not listed here, please include/edit -->
    </developers>
</project>


text:
import numpy as np
import torch
import torch.nn as nn
from torch.nn.functional import relu

import lib.utils as utils
from lib.utils import get_device
from lib.encoder_decoder import *
from lib.likelihood_eval import *

from torch.distributions.multivariate_normal import MultivariateNormal
from torch.distributions.normal import Normal
from torch.nn.modules.rnn import GRUCell, LSTMCell, RNNCellBase

from torch.distributions.normal import Normal
from torch.distributions import Independent
from torch.nn.parameter import Parameter
from lib.base_models import Baseline, VAE_Baseline

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Exponential decay of the hidden states for RNN
# adapted from GRU-D implementation: https://github.com/zhiyongc/GRU-D/

# Exp decay between hidden states
class GRUCellExpDecay(RNNCellBase):
	def __init__(self, input_size, input_size_for_decay, hidden_size, device, bias=True):
		super(GRUCellExpDecay, self).__init__(input_size, hidden_size, bias, num_chunks=3)

		self.device = device
		self.input_size_for_decay = input_size_for_decay
		self.decay = nn.Sequential(nn.Linear(input_size_for_decay, 1),)
		utils.init_network_weights(self.decay)

	def gru_exp_decay_cell(self, input, hidden, w_ih, w_hh, b_ih, b_hh):
		# INPORTANT: assumes that cum delta t is the last dimension of the input
		batch_size, n_dims = input.size()

		# "input" contains the data, mask and also cumulative deltas for all inputs
		cum_delta_ts = input[:, -self.input_size_for_decay:]
		data = input[:, :-self.input_size_for_decay]

		decay = torch.exp( - torch.min(torch.max(
			torch.zeros([1]).to(self.device), self.decay(cum_delta_ts)),
			torch.ones([1]).to(self.device) * 1000 ))

		hidden = hidden * decay

		gi = torch.mm(data, w_ih.t()) + b_ih
		gh = torch.mm(hidden, w_hh.t()) + b_hh
		i_r, i_i, i_n = gi.chunk(3, 1)
		h_r, h_i, h_n = gh.chunk(3, 1)

		resetgate = torch.sigmoid(i_r + h_r)
		inputgate = torch.sigmoid(i_i + h_i)
		newgate = torch.tanh(i_n + resetgate * h_n)
		hy = newgate + inputgate * (hidden - newgate)
		return hy

	def forward(self, input, hx=None):
		# type: (Tensor, Optional[Tensor]) -> Tensor
		#self.check_forward_input(input)
		if hx is None:
			hx = torch.zeros(input.size(0), self.hidden_size, dtype=input.dtype, device=input.device)
		#self.check_forward_hidden(input, hx, '')

		return self.gru_exp_decay_cell(
			input, hx,
			self.weight_ih, self.weight_hh,
			self.bias_ih, self.bias_hh
		)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Imputation with a weighed average of previous value and empirical mean
# adapted from GRU-D implementation: https://github.com/zhiyongc/GRU-D/
def get_cum_delta_ts(data, delta_ts, mask):
	n_traj, n_tp, n_dims = data.size()

	cum_delta_ts = delta_ts.repeat(1, 1, n_dims)
	missing_index = np.where(mask.cpu().numpy() == 0)

	for idx in range(missing_index[0].shape[0]):
		i = missing_index[0][idx]
		j = missing_index[1][idx]
		k = missing_index[2][idx]

		if j != 0 and j != (n_tp-1):
		 	cum_delta_ts[i,j+1,k] = cum_delta_ts[i,j+1,k] + cum_delta_ts[i,j,k]
	cum_delta_ts = cum_delta_ts / cum_delta_ts.max() # normalize

	return cum_delta_ts

# adapted from GRU-D implementation: https://github.com/zhiyongc/GRU-D/
# very slow
def impute_using_input_decay(data, delta_ts, mask, w_input_decay, b_input_decay):
	n_traj, n_tp, n_dims = data.size()

	cum_delta_ts = delta_ts.repeat(1, 1, n_dims)
	missing_index = np.where(mask.cpu().numpy() == 0)

	data_last_obsv = np.copy(data.cpu().numpy())
	for idx in range(missing_index[0].shape[0]):
		i = missing_index[0][idx]
		j = missing_index[1][idx]
		k = missing_index[2][idx]

		if j != 0 and j != (n_tp-1):
		 	cum_delta_ts[i,j+1,k] = cum_delta_ts[i,j+1,k] + cum_delta_ts[i,j,k]
		if j != 0:
			data_last_obsv[i,j,k] = data_last_obsv[i,j-1,k] # last observation
	cum_delta_ts = cum_delta_ts / cum_delta_ts.max() # normalize

	data_last_obsv = torch.Tensor(data_last_obsv).to(get_device(data))

	zeros = torch.zeros([n_traj, n_tp, n_dims]).to(get_device(data))
	decay = torch.exp( - torch.min( torch.max(zeros,
		w_input_decay * cum_delta_ts + b_input_decay), zeros + 1000 ))

	data_means = torch.mean(data, 1).unsqueeze(1)

	data_imputed = data * mask + (1-mask) * (decay * data_last_obsv + (1-decay) * data_means)
	return data_imputed

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

def run_rnn(inputs, delta_ts, cell, first_hidden=None,
	mask = None, feed_previous=False, n_steps=0,
	decoder = None, input_decay_params = None,
	feed_previous_w_prob = 0.,
	masked_update = True):
	if (feed_previous or feed_previous_w_prob) and decoder is None:
		raise Exception("feed_previous is set to True -- please specify RNN decoder")

	if n_steps == 0:
		n_steps = inputs.size(1)

	if (feed_previous or feed_previous_w_prob) and mask is None:
		mask = torch.ones((inputs.size(0), n_steps, inputs.size(-1))).to(get_device(inputs))

	if isinstance(cell, GRUCellExpDecay):
		cum_delta_ts = get_cum_delta_ts(inputs, delta_ts, mask)

	if input_decay_params is not None:
		w_input_decay, b_input_decay = input_decay_params
		inputs = impute_using_input_decay(inputs, delta_ts, mask,
			w_input_decay, b_input_decay)

	all_hiddens = []
	hidden = first_hidden

	if hidden is not None:
		all_hiddens.append(hidden)
		n_steps -= 1

	for i in range(n_steps):
		delta_t = delta_ts[:,i]
		if i == 0:
			rnn_input = inputs[:,i]
		elif feed_previous:
			rnn_input = decoder(hidden)
		elif feed_previous_w_prob > 0:
			feed_prev = np.random.uniform() > feed_previous_w_prob
			if feed_prev:
				rnn_input = decoder(hidden)
			else:
				rnn_input = inputs[:,i]
		else:
			rnn_input = inputs[:,i]

		if mask is not None:
			mask_i = mask[:,i,:]
			rnn_input = torch.cat((rnn_input, mask_i), -1)

		if isinstance(cell, GRUCellExpDecay):
			cum_delta_t = cum_delta_ts[:,i]
			input_w_t = torch.cat((rnn_input, cum_delta_t), -1).squeeze(1)
		else:
			input_w_t = torch.cat((rnn_input, delta_t), -1).squeeze(1)

		prev_hidden = hidden
		hidden = cell(input_w_t, hidden)

		if masked_update and (mask is not None) and (prev_hidden is not None):
			# update only the hidden states for hidden state only if at least one feature is present for the current time point
			summed_mask = (torch.sum(mask_i, -1, keepdim = True) > 0).float()
			assert(not torch.isnan(summed_mask).any())
			hidden = summed_mask * hidden + (1-summed_mask) * prev_hidden

		all_hiddens.append(hidden)

	all_hiddens = torch.stack(all_hiddens, 0)
	all_hiddens = all_hiddens.permute(1,0,2).unsqueeze(0)
	return hidden, all_hiddens

class Classic_RNN(Baseline):
	def __init__(self, input_dim, latent_dim, device,
		concat_mask = False, obsrv_std = 0.1,
		use_binary_classif = False,
		linear_classifier = False,
		classif_per_tp = False,
		input_space_decay = False,
		cell = "gru", n_units = 100,
		n_labels = 1,
		train_classif_w_reconstr = False):

		super(Classic_RNN, self).__init__(input_dim, latent_dim, device,
			obsrv_std = obsrv_std,
			use_binary_classif = use_binary_classif,
			classif_per_tp = classif_per_tp,
			linear_classifier = linear_classifier,
			n_labels = n_labels,
			train_classif_w_reconstr = train_classif_w_reconstr)

		self.concat_mask = concat_mask

		encoder_dim = int(input_dim)
		if concat_mask:
			encoder_dim = encoder_dim * 2

		self.decoder = nn.Sequential(
			nn.Linear(latent_dim, n_units),
			nn.Tanh(),
			nn.Linear(n_units, input_dim),)

		#utils.init_network_weights(self.encoder)
		utils.init_network_weights(self.decoder)

		if cell == "gru":
			self.rnn_cell = GRUCell(encoder_dim + 1, latent_dim) # +1 for delta t
		elif cell == "expdecay":
			self.rnn_cell = GRUCellExpDecay(
				input_size = encoder_dim,
				input_size_for_decay = input_dim,
				hidden_size = latent_dim,
				device = device)
		else:
			raise Exception("Unknown RNN cell: {}".format(cell))

		if input_space_decay:
			self.w_input_decay =  Parameter(torch.Tensor(1, int(input_dim))).to(self.device)
			self.b_input_decay =  Parameter(torch.Tensor(1, int(input_dim))).to(self.device)
		self.input_space_decay = input_space_decay

		self.z0_net = lambda hidden_state: hidden_state

	def get_reconstruction(self, time_steps_to_predict, data, truth_time_steps,
		mask = None, n_traj_samples = 1, mode = None):

		assert(mask is not None)
		n_traj, n_tp, n_dims = data.size()

		if (len(truth_time_steps) != len(time_steps_to_predict)) or (torch.sum(time_steps_to_predict - truth_time_steps) != 0):
			raise Exception("Extrapolation mode not implemented for RNN models")

		# for classic RNN time_steps_to_predict should be the same as  truth_time_steps
		assert(len(truth_time_steps) == len(time_steps_to_predict))

		batch_size = data.size(0)
		zero_delta_t = torch.Tensor([0.]).to(self.device)

		delta_ts = truth_time_steps[1:] - truth_time_steps[:-1]
		delta_ts = torch.cat((delta_ts, zero_delta_t))
		if len(delta_ts.size()) == 1:
			# delta_ts are shared for all trajectories in a batch
			assert(data.size(1) == delta_ts.size(0))
			delta_ts = delta_ts.unsqueeze(-1).repeat((batch_size,1,1))

		input_decay_params = None
		if self.input_space_decay:
			input_decay_params = (self.w_input_decay, self.b_input_decay)

		if mask is not None:
			utils.check_mask(data, mask)

		hidden_state, all_hiddens = run_rnn(data, delta_ts,
			cell = self.rnn_cell, mask = mask,
			input_decay_params = input_decay_params,
			feed_previous_w_prob = (0. if self.use_binary_classif else 0.5),
			decoder = self.decoder)

		outputs = self.decoder(all_hiddens)
		# Shift outputs for computing the loss -- we should compare the first output to the second data point, etc.
		first_point = data[:,0,:]
		outputs = utils.shift_outputs(outputs, first_point)

		extra_info = {"first_point": (hidden_state.unsqueeze(0), 0.0, hidden_state.unsqueeze(0))}

		if self.use_binary_classif:
			if self.classif_per_tp:
				extra_info["label_predictions"] = self.classifier(all_hiddens)
			else:
				extra_info["label_predictions"] = self.classifier(hidden_state).reshape(1,-1)

		# outputs shape: [n_traj_samples, n_traj, n_tp, n_dims]
		return outputs, extra_info

class RNN_VAE(VAE_Baseline):
	def __init__(self, input_dim, latent_dim, rec_dims,
		z0_prior, device,
		concat_mask = False, obsrv_std = 0.1,
		input_space_decay = False,
		use_binary_classif = False,
		classif_per_tp =False,
		linear_classifier = False,
		cell = "gru", n_units = 100,
		n_labels = 1,
		train_classif_w_reconstr = False):

		super(RNN_VAE, self).__init__(
			input_dim = input_dim, latent_dim = latent_dim,
			z0_prior = z0_prior,
			device = device, obsrv_std = obsrv_std,
			use_binary_classif = use_binary_classif,
			classif_per_tp = classif_per_tp,
			linear_classifier = linear_classifier,
			n_labels = n_labels,
			train_classif_w_reconstr = train_classif_w_reconstr)

		self.concat_mask = concat_mask

		encoder_dim = int(input_dim)
		if concat_mask:
			encoder_dim = encoder_dim * 2

		if cell == "gru":
			self.rnn_cell_enc = GRUCell(encoder_dim + 1, rec_dims) # +1 for delta t
			self.rnn_cell_dec = GRUCell(encoder_dim + 1, latent_dim) # +1 for delta t
		elif cell == "expdecay":
			self.rnn_cell_enc = GRUCellExpDecay(
				input_size = encoder_dim,
				input_size_for_decay = input_dim,
				hidden_size = rec_dims,
				device = device)
			self.rnn_cell_dec = GRUCellExpDecay(
				input_size = encoder_dim,
				input_size_for_decay = input_dim,
				hidden_size = latent_dim,
				device = device)
		else:
			raise Exception("Unknown RNN cell: {}".format(cell))

		self.z0_net = nn.Sequential(
			nn.Linear(rec_dims, n_units),
			nn.Tanh(),
			nn.Linear(n_units, latent_dim * 2),)
		utils.init_network_weights(self.z0_net)

		self.decoder = nn.Sequential(
			nn.Linear(latent_dim, n_units),
			nn.Tanh(),
			nn.Linear(n_units, input_dim),)

		#utils.init_network_weights(self.encoder)
		utils.init_network_weights(self.decoder)

		if input_space_decay:
			self.w_input_decay =  Parameter(torch.Tensor(1, int(input_dim))).to(self.device)
			self.b_input_decay =  Parameter(torch.Tensor(1, int(input_dim))).to(self.device)
		self.input_space_decay = input_space_decay

	def get_reconstruction(self, time_steps_to_predict, data, truth_time_steps,
		mask = None, n_traj_samples = 1, mode = None):

		assert(mask is not None)

		batch_size = data.size(0)
		zero_delta_t = torch.Tensor([0.]).to(self.device)

		# run encoder backwards
		run_backwards = bool(time_steps_to_predict[0] < truth_time_steps[-1])

		if run_backwards:
			# Look at data in the reverse order: from later points to the first
			data = utils.reverse(data)
			mask = utils.reverse(mask)

		delta_ts = truth_time_steps[1:] - truth_time_steps[:-1]
		if run_backwards:
			# we are going backwards in time
			delta_ts = utils.reverse(delta_ts)

		delta_ts = torch.cat((delta_ts, zero_delta_t))
		if len(delta_ts.size()) == 1:
			# delta_ts are shared for all trajectories in a batch
			assert(data.size(1) == delta_ts.size(0))
			delta_ts = delta_ts.unsqueeze(-1).repeat((batch_size,1,1))

		input_decay_params = None
		if self.input_space_decay:
			input_decay_params = (self.w_input_decay, self.b_input_decay)

		hidden_state, _ = run_rnn(data, delta_ts,
			cell = self.rnn_cell_enc, mask = mask,
			input_decay_params = input_decay_params)

		z0_mean, z0_std = utils.split_last_dim(self.z0_net(hidden_state))
		z0_std = z0_std.abs()
		z0_sample = utils.sample_standard_gaussian(z0_mean, z0_std)

		# Decoder # # # # # # # # # # # # # # # # # # # #
		delta_ts = torch.cat((zero_delta_t, time_steps_to_predict[1:] - time_steps_to_predict[:-1]))
		if len(delta_ts.size()) == 1:
			delta_ts = delta_ts.unsqueeze(-1).repeat((batch_size,1,1))

		_, all_hiddens = run_rnn(data, delta_ts,
			cell = self.rnn_cell_dec,
			first_hidden = z0_sample, feed_previous = True,
			n_steps = time_steps_to_predict.size(0),
			decoder = self.decoder,
			input_decay_params = input_decay_params)

		outputs = self.decoder(all_hiddens)
		# Shift outputs for computing the loss -- we should compare the first output to the second data point, etc.
		first_point = data[:,0,:]
		outputs = utils.shift_outputs(outputs, first_point)

		extra_info = {"first_point": (z0_mean.unsqueeze(0), z0_std.unsqueeze(0), z0_sample.unsqueeze(0))}

		if self.use_binary_classif:
			if self.classif_per_tp:
				extra_info["label_predictions"] = self.classifier(all_hiddens)
			else:
				extra_info["label_predictions"] = self.classifier(z0_mean).reshape(1,-1)

		# outputs shape: [n_traj_samples, n_traj, n_tp, n_dims]
		return outputs, extra_info


text:
import java.util.Scanner;

class AddNumbers {
	public	static	void main(String args[]){

		int	num1, num2, result;

		Scanner in = new Scanner(System.in)

		System.out.println("Enter first number: ");
		num1 = Integer.parseInt(in.nextLine());

		System.out.println("Enter second number: ");
		num2 = Integer.parseInt(in.nextLine());

		result =num1 + num2;
		System.out.println("Sum of entered integers = " + result);

	}
}


text:
using System;
using System.Threading;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Mapping;
using Umbraco.Core.PackageActions;
using Umbraco.Core.Packaging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Web.Actions;
using Umbraco.Web.Cache;
using Umbraco.Web.Editors;
using Umbraco.Web.HealthCheck;
using Umbraco.Web.Mvc;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Services;
using Umbraco.Web.WebApi;

using CoreCurrent = Umbraco.Core.Composing.Current;

namespace Umbraco.Web.Composing
{
    // see notes in Umbraco.Core.Composing.Current.
    public static class Current
    {
        private static readonly object Locker = new object();

        private static IUmbracoContextAccessor _umbracoContextAccessor;

        static Current()
        {
            CoreCurrent.Resetted += (sender, args) =>
            {
                if (_umbracoContextAccessor != null)
                {
                    var umbracoContext = _umbracoContextAccessor.UmbracoContext;
                    umbracoContext?.Dispose();
                }
                _umbracoContextAccessor = null;
            };
        }

        // for UNIT TESTS exclusively!
        internal static void Reset()
        {
            CoreCurrent.Reset();
        }

        /// <summary>
        /// Gets the factory.
        /// </summary>
        public static IFactory Factory
            => CoreCurrent.Factory;

        #region Temp & Special

        // TODO: have to keep this until tests are refactored
        // but then, it should all be managed properly in the container
        public static IUmbracoContextAccessor UmbracoContextAccessor
        {
            get
            {
                if (_umbracoContextAccessor != null) return _umbracoContextAccessor;
                return _umbracoContextAccessor = Factory.GetInstance<IUmbracoContextAccessor>();
            }
            set => _umbracoContextAccessor = value; // for tests
        }

        #endregion

        #region Web Getters

        public static UmbracoContext UmbracoContext
            => UmbracoContextAccessor.UmbracoContext;

        public static UmbracoHelper UmbracoHelper
            => Factory.GetInstance<UmbracoHelper>();

        public static DistributedCache DistributedCache
            => Factory.GetInstance<DistributedCache>();

        public static IPublishedSnapshot PublishedSnapshot
            => Factory.GetInstance<IPublishedSnapshotAccessor>().PublishedSnapshot;

        public static EventMessages EventMessages
            => Factory.GetInstance<IEventMessagesFactory>().GetOrDefault();

        public static UrlProviderCollection UrlProviders
            => Factory.GetInstance<UrlProviderCollection>();

        public static MediaUrlProviderCollection MediaUrlProviders
            => Factory.GetInstance<MediaUrlProviderCollection>();

        public static HealthCheckCollectionBuilder HealthCheckCollectionBuilder
            => Factory.GetInstance<HealthCheckCollectionBuilder>();

        internal static ActionCollectionBuilder ActionCollectionBuilder
            => Factory.GetInstance<ActionCollectionBuilder>();

        public static ActionCollection Actions
            => Factory.GetInstance<ActionCollection>();

        public static ContentFinderCollection ContentFinders
            => Factory.GetInstance<ContentFinderCollection>();

        public static IContentLastChanceFinder LastChanceContentFinder
            => Factory.GetInstance<IContentLastChanceFinder>();

        internal static EditorValidatorCollection EditorValidators
            => Factory.GetInstance<EditorValidatorCollection>();

        internal static UmbracoApiControllerTypeCollection UmbracoApiControllerTypes
            => Factory.GetInstance<UmbracoApiControllerTypeCollection>();

        internal static SurfaceControllerTypeCollection SurfaceControllerTypes
            => Factory.GetInstance<SurfaceControllerTypeCollection>();

        public static FilteredControllerFactoryCollection FilteredControllerFactories
            => Factory.GetInstance<FilteredControllerFactoryCollection>();

        internal static IPublishedSnapshotService PublishedSnapshotService
            => Factory.GetInstance<IPublishedSnapshotService>();

        public static ITreeService TreeService
            => Factory.GetInstance<ITreeService>();

        public static ISectionService SectionService
            => Factory.GetInstance<ISectionService>();

        #endregion

        #region Web Constants

        // these are different - not 'resolving' anything, and nothing that could be managed
        // by the container - just registering some sort of application-wide constants or
        // settings - but they fit in Current nicely too

        private static Type _defaultRenderMvcControllerType;

        // internal - can only be accessed through Composition at compose time
        internal static Type DefaultRenderMvcControllerType
        {
            get => _defaultRenderMvcControllerType;
            set
            {
                if (value.Implements<IRenderController>() == false)
                    throw new ArgumentException($"Type {value.FullName} does not implement {typeof (IRenderController).FullName}.", nameof(value));
                _defaultRenderMvcControllerType = value;
            }
        }

        #endregion

        #region Core Getters

        // proxy Core for convenience

        public static UmbracoMapper Mapper => CoreCurrent.Mapper;

        public static IRuntimeState RuntimeState => CoreCurrent.RuntimeState;

        public static TypeLoader TypeLoader => CoreCurrent.TypeLoader;

        public static Configs Configs => CoreCurrent.Configs;

        public static UrlSegmentProviderCollection UrlSegmentProviders => CoreCurrent.UrlSegmentProviders;

        public static CacheRefresherCollection CacheRefreshers => CoreCurrent.CacheRefreshers;

        public static DataEditorCollection DataEditors => CoreCurrent.DataEditors;

        public static PropertyEditorCollection PropertyEditors => CoreCurrent.PropertyEditors;

        public static ParameterEditorCollection ParameterEditors => CoreCurrent.ParameterEditors;

        internal static ManifestValueValidatorCollection ManifestValidators => CoreCurrent.ManifestValidators;

        internal static IPackageActionRunner PackageActionRunner => CoreCurrent.PackageActionRunner;

        internal static PackageActionCollection PackageActions => CoreCurrent.PackageActions;

        internal static PropertyValueConverterCollection PropertyValueConverters => CoreCurrent.PropertyValueConverters;

        internal static IPublishedModelFactory PublishedModelFactory => CoreCurrent.PublishedModelFactory;

        public static IServerMessenger ServerMessenger => CoreCurrent.ServerMessenger;

        public static IServerRegistrar ServerRegistrar => CoreCurrent.ServerRegistrar;

        public static ICultureDictionaryFactory CultureDictionaryFactory => CoreCurrent.CultureDictionaryFactory;

        public static IShortStringHelper ShortStringHelper => CoreCurrent.ShortStringHelper;

        public static ILogger Logger => CoreCurrent.Logger;

        public static IProfiler Profiler => CoreCurrent.Profiler;

        public static IProfilingLogger ProfilingLogger => CoreCurrent.ProfilingLogger;

        public static AppCaches AppCaches => CoreCurrent.AppCaches;

        public static ServiceContext Services => CoreCurrent.Services;

        public static IScopeProvider ScopeProvider => CoreCurrent.ScopeProvider;

        public static IFileSystems FileSystems => CoreCurrent.FileSystems;

        public static ISqlContext SqlContext=> CoreCurrent.SqlContext;

        public static IPublishedContentTypeFactory PublishedContentTypeFactory => CoreCurrent.PublishedContentTypeFactory;

        public static IPublishedValueFallback PublishedValueFallback => CoreCurrent.PublishedValueFallback;

        public static IVariationContextAccessor VariationContextAccessor => CoreCurrent.VariationContextAccessor;

        #endregion
    }
}


text:
<?php

interface TestInterface {}
class TestClass {}
interface DerivedInterface extends TestInterface {}

$reflectionClass = new ReflectionClass('TestInterface');
$reflectionClass2 = new ReflectionClass('TestClass');
$reflectionClass3 = new ReflectionClass('DerivedInterface');

var_dump($reflectionClass->isInterface());
var_dump($reflectionClass2->isInterface());
var_dump($reflectionClass3->isInterface());

?>


text:
var pjson = require('../package.json');
console.log(pjson.version);


text:
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright 2016 Open Networking Laboratory
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~     http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<drivers>
    <driver name="foo.0" manufacturer="Circus" hwVersion="1.2" swVersion="2.0">
        <behaviour api="org.onosproject.net.driver.TestBehaviour"
                   impl="org.onosproject.net.driver.TestBehaviourImpl"/>
    </driver>

    <driver name="foo.1" extends="foo.0" manufacturer="Circus" hwVersion="1.2a" swVersion="2.2">
        <fingerprint>ding</fingerprint>
        <fingerprint>bat</fingerprint>

        <behaviour api="org.onosproject.net.driver.TestBehaviour"
                   impl="org.onosproject.net.driver.TestBehaviourImpl2"/>
        <behaviour api="org.onosproject.net.driver.TestBehaviourTwo"
                   impl="org.onosproject.net.driver.TestBehaviourTwoImpl"/>

        <property name="p1">v1</property>
        <property name="p2">v2</property>
    </driver>

    <driver name="foo.2" extends="foo.0,foo.1" manufacturer="Circus" hwVersion="1.2" swVersion="2.0">
        <behaviour api="org.onosproject.net.driver.TestBehaviourThree"
                   impl="org.onosproject.net.driver.TestBehaviourThreeImpl"/>
    </driver>
</drivers>


text:
  {{form.title}}

    <ui-select ng-model="select_model.selected" theme="bootstrap" ng-disabled="form.disabled" on-select="$$value$$=$item.value" class="{{form.options.uiClass}}">
      <ui-select-match placeholder="{{form.placeholder || form.schema.placeholder || ('placeholders.select' | translate)}}">{{select_model.selected.label}}</ui-select-match>
      <ui-select-choices repeat="item in form.schema.items | propsFilter: {label: $select.search}"
             refresh="form.options.refreshMethod(form.schema, $select.search)"
             refresh-delay="form.options.refreshDelay">

      </ui-select-choices>
    </ui-select>
    <input type="hidden" toggle-single-model sf-changed="form" ng-model="insideModel" schema-validate="form" />


text:
/*Much of the default CSS that styles Yana is provided by the JQuery Mobile library. This file provides CSS code that supplements (and in some cases replaces) JQuery Mobile's CSS settings).*/

/*<---------------------General--------------------->*/
/* Basic fonts and positioning*/
body {
	margin: 0;
	padding: 0;
	font: 14px/16px Helvetica;
}

/*Background image for application*/
.ui-body-c, .ui-body-c select, .ui-body-c textarea, .ui-body-c button {
	background-image: url(img/brushed_alu_dark.png);
}

/*Padding of content area (menus, etc.)*/
.ui-content {
	padding: 5px;
}

/* Prevents image rounding from inheriting border-radius property; Positions image thumbs (all non-home-icon imgs) */
.ui-mobile a img {
	border-radius: 0px;
}

/* Positions and limits the size of images associated with non-home menus (e.g., a list of previous issues with images of the covers) */
.ui-li-thumb, .ui-li-icon {
	max-height: 70px;
	max-width: 70px;
	padding: 5px;
}

/*<---------------------Navigation------------------->*/

/*Applies spacing to the right and left of the home menu*/
ul#homeSection1List, ul#homeSection2List  {
	margin: 1em 15px;
}

/* Icon positioning and sizing for the home menu */
ul#homeSection1List li img, ul#homeSection2List li img {
	 top: 11px;
	 max-height: 40px;
	 max-width: 40px;
	 padding: 0px;
	}

ul#homeSection1List li a, ul#homeSection2List li a {
	padding: 20px 0px 20px 70px;
}

/*<---------------------Internal Pages------------------->*/

/*White background, rounded corners for html content (e.g., article text)*/
#articleContent, .htmlContent.ui-content, .opensearchContent {
	background: #FFF;
	margin: 8px;
	padding: 10px 15px 20px 25px;
	-moz-border-radius: 10px;
	border-radius: 10px;
}
/* Images in html content are floated left, allowing text to wrap around them. */
#articleContent img {
	float:left;
	margin-right: 5px;
}


text:
package com.sproutigy.commons.jsonright.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

import static com.fasterxml.jackson.core.JsonToken.END_OBJECT;
import static com.fasterxml.jackson.core.JsonToken.START_OBJECT;

@JsonSerialize(using=ClassedJSON.MySerializer.class)
@JsonDeserialize(using=ClassedJSON.MyDeserializer.class)
public final class ClassedJSON {
    private Object value;

    public ClassedJSON() { }

    public ClassedJSON(Object value) {
        this.value = value;
    }

    @SuppressWarnings("unchecked")
    public <T> T get() {
        return (T)value;
    }

    @SuppressWarnings("unchecked")
    public <T> T get(Class<T> clazz) {
        return (T)value;
    }

    public void set(Object value) {
        this.value = value;
    }

    public JSON asJSON() {
        return JSON.serialize(this);
    }

    public boolean isEmpty() {
        return value == null;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ClassedJSON that = (ClassedJSON) o;

        return value != null ? value.equals(that.value) : that.value == null;

    }

    @Override
    public int hashCode() {
        return value != null ? value.hashCode() : 0;
    }

    @Override
    public String toString() {
        if (value != null) {
            return value.toString();
        }
        return "null";
    }

    public static JSON serialize(Object o) {
        return new ClassedJSON(o).asJSON();
    }

    public static <T> T deserialize(String json) {
        return deserialize(new JSON(json));
    }

    public static <T> T deserialize(JSON json) {
        return json.deserialize(ClassedJSON.class).get();
    }

    public static String fetchClassName(String json) {
        return fetchClassName(JSON.fromString(json));
    }

    public static String fetchClassName(JSON json) {
        return json.nodeObject().fields().next().getKey();
    }

    static class MySerializer extends StdSerializer<ClassedJSON> {

        public MySerializer() {
            this(null);
        }

        public MySerializer(Class<ClassedJSON> t) {
            super(t);
        }

        @Override
        public void serialize(ClassedJSON classedJSON, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            Object value = classedJSON.get();
            jsonGenerator.writeStartObject();
            if (value != null) {
                jsonGenerator.writeFieldName(value.getClass().getName());
                jsonGenerator.writeObject(value);
            }
            jsonGenerator.writeEndObject();
        }
    }

    static class MyDeserializer extends StdDeserializer<ClassedJSON> {

        public MyDeserializer() {
            this(null);
        }

        public MyDeserializer(Class<?> vc) {
            super(vc);
        }

        @Override
        public ClassedJSON deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            ClassedJSON ret = new ClassedJSON();

            JsonToken currentToken;
            while ((currentToken = jsonParser.nextValue()) != null) {
                if (currentToken == START_OBJECT) {
                    String className = jsonParser.getCurrentName();
                    try {
                        Object val = jsonParser.readValueAs(Class.forName(className));
                        ret.set(val);
                    } catch (ClassNotFoundException e) {
                        throw new IOException("Class not found: " + className, e);
                    }
                }
                if (currentToken == END_OBJECT) {
                    return ret;
                }
            }

            return ret;
        }
    }
}


text:
# Strassen Matrix Multiplication

## Goal
+ To quickly perform a matrix multiplication operation on two matricies

## What is Matrix Multiplication??

> Note: If you are already familiar with Linear Algebra/Matrix Multiplication, feel free to skip this section

Before we begin, you may ask what is matrix multiplication? Great question! It is **NOT** multiplying two matricies term-by-term. Matrix multiplication is a mathematical operation that combines two matricies into a single one. Sounds like multiplying term-by-term huh? It's not... our lives would be much easier if it were. To see how matrix multiplcation works, let's look at an example.

### Example: Matrix Multiplication

```
matrix A = |1 2|, matrix B = |5 6|
           |3 4|             |7 8|

A * B = C

|1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22|
|3 4|   |7 8|   |3*5+4*7 3*6+4*8|   |43 50|
```

What's going on here? To start, we're multiplying matricies A & B. Our new matrix, C's, elements `[i, j]` are determined by the dot product of the first matrix's ith row and the second matrix's jth column. See [here](https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces/dot-cross-products/v/vector-dot-product-and-vector-length) for a refresher on the dot product.

So the upper left element `[i=1, j=1]` of our new matrix is a combination of A's 1st row and B's 1st column.

	A's first row = [1, 2]
	B's first column = [5, 7]

	[1, 2] dot [5, 7] = [1*5 + 2*7] = [19] = C[1, 1]

Now let's try this for `[i=1, j=2]`. Because `i=1` and `j=2`, this will represent the upper right element in our new matrix, C.

	A's first row = [1, 2]
	B's second column = [6, 8]

	[1, 2] dot [6, 8] = [1*6 + 2*8] = [22] = C[1, 2]

If we do this for each row & column of A & B we'll get our result matrix C!

Here's a great graphic that visually shows you what's going on.

![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png)

[Source](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png)

## Matix Multiplication Algorithm

So how do we implement matrix multiplication in an algoirthm? We'll start with the basic version and from there move on to Strassen's Algorithm.

+ [Basic Version](#basic-version)
+ [Strassen's Algorithm](#strassens-algorithm)

### Basic Version

Remember the method we used to solve matrix multiplication [above](#what-is-matrix-multiplication??)? Let's try to implement that first! We first assert that the two matricies are the right size.

`assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")`

> **NOTE:** A's # of columns HAS to equal B's # of rows for matrix multiplication to work

Next, we loop over A's columns and B's rows. Because we know both A's columns & B's rows are the same length, we set that length equal to `n`.

```swift
for i in 0..<n {
  for j in 0..<n {
```

Then, for each row in A and column in B, we take the dot product of the ith row in A with the jth column in B and set that result equal to the `[i, j]` element in C. Or `C[i, j]`.

```swift
for k in 0..<n {
  C[i, j] += A[i, k] * B[k, j]
}
```

Finally, we return our new matrix C!

Here's the full implementation:

```swift
public func matrixMultiply(by B: Matrix<T>) -> Matrix<T> {
  let A = self
  assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")
  let n = A.columns
  var C = Matrix<T>(rows: A.rows, columns: B.columns)

  for i in 0..<n {
    for j in 0..<n {
      for k in 0..<n {
        C[i, j] += A[i, k] * B[k, j]
      }
    }
  }

  return C
}
```

This algorithm has a runtime of **O(n^3)**. The **O(n^3)** comes from the three `for` loops. Two from the loop over the rows & columns and one from the dot product!

Now, **O(n^3)** is not very fast and a great question we should ask is can we do better? Indeed we can!

### Strassens Algorithm

Volker Strassen first published his algorithm in 1969. It was the first algorithm to prove that the basic **O(n^3)** runtime was not optiomal.

The basic idea behind Strassen's algorithm is to split A & B into 8 submatricies and then recursively compute the submatricies of C. This strategy is called *Divide and Conquer*.

```
matrix A = |a b|, matrix B = |e f|
           |c d|             |g h|
```

*There will be 8 recursive calls:*

1. a * e
2. b * g
3. a * f
4. b * h
5. c * e
6. d * g
7. c * f
8. d * h

We then use these results to compute C's submatricies.

	matrix C = |ae+bg af+bh|
			   |ce+dg cf+dh|

![http://d1hyf4ir1gqw6c.cloudfront.net//wp-content/uploads/strassen_new.png](http://d1hyf4ir1gqw6c.cloudfront.net//wp-content/uploads/strassen_new.png)

This step alone, however, doesn't help our runtime at all. Using the [Master Theorem](https://en.wikipedia.org/wiki/Master_theorem) with `T(n) = 8T(n/2) + O(n^2)` we still get a runtime of `O(n^3)`.

Strassen's insight was that we don't actually need **8** recursive calls to complete this process. We can finish the call with **7** recursive calls and a little bit of addition and subtraction.

Strassen's **7** calls are as follows:

1. a * (f - h)
2. (a + b) * h
3. (c + d) * e
4. d * (g - e)
5. (a + d) * (e + h)
6. (b - d) * (g + h)
7. (a - c) * (e + f)

Now we can compute our new matrix C's new quardents!

```
matrix C = |p5+p4-p2+p6    p1+p2   |
           |   p3+p4    p1+p5-p3-p7|
```

A great reaction right now would be !!??!?!?!!?! How does this even work??

Let's prove it!

**First** Submatrix:

```
p5+p4-p2+p6 = (a+d)*(e+h) + d*(g-e) - (a+b)*h + (b-d)*(g+h)
            = (ae+de+ah+dh) + (dg-de) - (ah+bh) + (bg-dg+bh-dh)
            = ae+bg ✅
```

Exactly what we got the first time!

Now let's prove the others.

**Second** submatrix:

```
p1+p2 = a*(f-h) + (a+b)*h
      = (af-ah) + (ah+bh)
      = af+bh ✅
```

**Third** submatrix:

```
p3+p4 = (c+d)*e + d*(g-e)
      = (ce+de) + (dg-de)
      = ce+dg ✅
```

**Fourth** submatrix:

```
p1+p5-p3-p7 = a*(f-h) + (a+d)*(e+h) - (c+d)*e - (a-c)*(e+f)
            = (af-ah) + (ae+de+ah+dh) -(ce+de) - (ae-ce+af-cf)
            = cf+dh ✅
```

Great! The math checks out!

Here's the process in action.

![](http://d1hyf4ir1gqw6c.cloudfront.net//wp-content/uploads/stressen_formula_new_new.png)

[Source](http://www.geeksforgeeks.org/strassens-matrix-multiplication/)

#### Implementation

Ok so now to the implementation. We'll start with the same first step from the basic implementation. We need to assert that A's # of columns are equal to B's number of rows.

	assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")

Now time for some prep work! We make each matrix a square and increase it's size to the next power of two. This ensures makes Strassen's Algorithm much easier to manage. We now only need to deal with square matricies that can be broken up an even number of times!

```swift
let n = max(A.rows, A.columns, B.rows, B.columns)
let m = nextPowerOfTwo(after: n)

var APrep = Matrix(size: m)
var BPrep = Matrix(size: m)

for i in A.rows {
  for j in A.columns {
    APrep[i, j] = A[i,j]
  }
}

for i in B.rows {
  for j in B.columns {
    BPrep[i, j] = B[i, j]
  }
}
```

Finally, we recursively compute the matrix using Strassen's algorithm and the transform our new matrix `C` back to the correct dimensions!

```swift
let CPrep = APrep.strassenR(by: BPrep)
var C = Matrix(rows: A.rows, columns: B.columns)

for i in 0..<A.rows {
  for j in 0..<B.columns {
    C[i,j] = CPrep[i,j]
  }
}
```

#### Recursively Computing the Matrix Multiplication

Next let's explore this recursive function `strassenR`.

We start by initializing 8 submatricies.

```swift
var a = Matrix(size: nBy2)
var b = Matrix(size: nBy2)
var c = Matrix(size: nBy2)
var d = Matrix(size: nBy2)
var e = Matrix(size: nBy2)
var f = Matrix(size: nBy2)
var g = Matrix(size: nBy2)
var h = Matrix(size: nBy2)

for i in 0..<nBy2 {
  for j in 0..<nBy2 {
    a[i,j] = A[i,j]
    b[i,j] = A[i, j+nBy2]
    c[i,j] = A[i+nBy2, j]
    d[i,j] = A[i+nBy2, j+nBy2]
    e[i,j] = B[i,j]
    f[i,j] = B[i, j+nBy2]
    g[i,j] = B[i+nBy2, j]
    h[i,j] = B[i+nBy2, j+nBy2]
  }
}
```

We next recursively compute the 7 matrix multiplications.

```swift
let p1 = a.strassenR(by: f-h)       // a * (f - h)
let p2 = (a+b).strassenR(by: h)     // (a + b) * h
let p3 = (c+d).strassenR(by: e)     // (c + d) * e
let p4 = d.strassenR(by: g-e)       // d * (g - e)
let p5 = (a+d).strassenR(by: e+h)   // (a + d) * (e + h)
let p6 = (b-d).strassenR(by: g+h)   // (b - d) * (g + h)
let p7 = (a-c).strassenR(by: e+f)   // (a - c) * (e + f)
```

Next, we compute the submatricies of C.

```swift
let c11 = p5 + p4 - p2 + p6         // p5 + p4 - p2 + p6
let c12 = p1 + p2                   // p1 + p2
let c21 = p3 + p4                   // p3 + p4
let c22 = p1 + p5 - p3 - p7         // p1 + p5 - p3 - p7
```

And finally, we combine these submatricies into our new matrix C!

```swift
var C = Matrix(size: n)
for i in 0..<nBy2 {
  for j in 0..<nBy2 {
    C[i, j]           = c11[i,j]
    C[i, j+nBy2]      = c12[i,j]
    C[i+nBy2, j]      = c21[i,j]
    C[i+nBy2, j+nBy2] = c22[i,j]
  }
}
```

As before, we can analyze the time completxity using the [Master Theorem](https://en.wikipedia.org/wiki/Master_theorem). `T(n) = 7T(n/2) +  O(n^2)` which leads to `O(n^log(7))` runtime. This comes out to approxiamtely `O(n^2.8074)` which is better than `O(n^3)`!

And that's Strassen's algorithm! Here's the full implementation:

```swift
// MARK: - Strassen Multiplication

extension Matrix {
  public func strassenMatrixMultiply(by B: Matrix<T>) -> Matrix<T> {
    let A = self
    assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")

    let n = max(A.rows, A.columns, B.rows, B.columns)
    let m = nextPowerOfTwo(after: n)

    var APrep = Matrix(size: m)
    var BPrep = Matrix(size: m)

    A.forEach { (i, j) in
      APrep[i,j] = A[i,j]
    }

    B.forEach { (i, j) in
      BPrep[i,j] = B[i,j]
    }

    let CPrep = APrep.strassenR(by: BPrep)
    var C = Matrix(rows: A.rows, columns: B.columns)
    for i in 0..<A.rows {
      for j in 0..<B.columns {
        C[i,j] = CPrep[i,j]
      }
    }

    return C
  }

  private func strassenR(by B: Matrix<T>) -> Matrix<T> {
    let A = self
    assert(A.isSquare && B.isSquare, "This function requires square matricies!")
    guard A.rows > 1 && B.rows > 1 else { return A * B }

    let n    = A.rows
    let nBy2 = n / 2

    /*
    Assume submatricies are allocated as follows

     matrix A = |a b|,    matrix B = |e f|
                |c d|                |g h|
    */

    var a = Matrix(size: nBy2)
    var b = Matrix(size: nBy2)
    var c = Matrix(size: nBy2)
    var d = Matrix(size: nBy2)
    var e = Matrix(size: nBy2)
    var f = Matrix(size: nBy2)
    var g = Matrix(size: nBy2)
    var h = Matrix(size: nBy2)

    for i in 0..<nBy2 {
      for j in 0..<nBy2 {
        a[i,j] = A[i,j]
        b[i,j] = A[i, j+nBy2]
        c[i,j] = A[i+nBy2, j]
        d[i,j] = A[i+nBy2, j+nBy2]
        e[i,j] = B[i,j]
        f[i,j] = B[i, j+nBy2]
        g[i,j] = B[i+nBy2, j]
        h[i,j] = B[i+nBy2, j+nBy2]
      }
    }

    let p1 = a.strassenR(by: f-h)       // a * (f - h)
    let p2 = (a+b).strassenR(by: h)     // (a + b) * h
    let p3 = (c+d).strassenR(by: e)     // (c + d) * e
    let p4 = d.strassenR(by: g-e)       // d * (g - e)
    let p5 = (a+d).strassenR(by: e+h)   // (a + d) * (e + h)
    let p6 = (b-d).strassenR(by: g+h)   // (b - d) * (g + h)
    let p7 = (a-c).strassenR(by: e+f)   // (a - c) * (e + f)

    let c11 = p5 + p4 - p2 + p6         // p5 + p4 - p2 + p6
    let c12 = p1 + p2                   // p1 + p2
    let c21 = p3 + p4                   // p3 + p4
    let c22 = p1 + p5 - p3 - p7         // p1 + p5 - p3 - p7

    var C = Matrix(size: n)
    for i in 0..<nBy2 {
      for j in 0..<nBy2 {
        C[i, j]           = c11[i,j]
        C[i, j+nBy2]      = c12[i,j]
        C[i+nBy2, j]      = c21[i,j]
        C[i+nBy2, j+nBy2] = c22[i,j]
      }
    }

    return C
  }

  private func nextPowerOfTwo(after n: Int) -> Int {
    return Int(pow(2, ceil(log2(Double(n)))))
  }
}
```

## Appendix

### Number Protocol

I use a number protocol to enable by Matrix to be generic.

The Number protocol ensures three things:

1. Everything that is a number can be multiplied
2. Everything that is a number can be added/subtracted
3. Everything that is a number has a zero value

Extending `Int`, `Float`, and `Double` to conform to this protocol is now very straightforward. All you need to do is implement the `static var zero`!

```swift
public protocol Number: Multipliable, Addable {
  static var zero: Self { get }
}

public protocol Addable {
  static func +(lhs: Self, rhs: Self) -> Self
  static func -(lhs: Self, rhs: Self) -> Self
}

public protocol Multipliable {
  static func *(lhs: Self, rhs: Self) -> Self
}
```

### Dot Product

I extend `Array` to include a dot product function for when the Array's element conform to the `Number` protocol.

```swift
extension Array where Element: Number {
  public func dot(_ b: Array<Element>) -> Element {
    let a = self
    assert(a.count == b.count, "Can only take the dot product of arrays of the same length!")
    let c = a.indices.map{ a[$0] * b[$0] }
    return c.reduce(Element.zero, { $0 + $1 })
  }
}
```

## Resources

+ [Intro to Matrix Multiplication | Khan Academy](https://www.khanacademy.org/math/precalculus/precalc-matrices/multiplying-matrices-by-matrices/v/matrix-multiplication-intro)
+ [Matrix Multiplication | Wikipedia](https://en.wikipedia.org/wiki/Matrix_multiplication)
+ [Strassen Algorithm | Wikipedia](https://en.wikipedia.org/wiki/Strassen_algorithm)
+ [Strassen Algorithm | Wolfram MathWorld](http://mathworld.wolfram.com/StrassenFormulas.html)
+ [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/)

*Written for Swift Algorithm Club by Richard Ash*


text:
package config

import (
	"io/ioutil"

	"github.com/go-yaml/yaml"
)

type Config struct {
	Server        bool   // Run as server, if different than false (server)
	Ip            string // Bind address, if different than 0.0.0.0 (server)
	Port          string // listen port, if different than '7777' (server)
	DbHandler     string // "mongo" (server)
	MongoHost     string // mongoDB host, if different than 'localhost' (server)
	MongoDbName   string // mongoDB db name, if different than 'filesrv' (server)
	MongoUsername string // mongoDB username, if any (server)
	MongoPassword string // mongoDB password, if any (server)

	RemoteHost string // imgsrv server to push files to (client)

	Map map[string]interface{} // key/value options (not used currently)
}

// Of the configurations, provided option, return the value as a bool
func (c Config) GetBool(option string) (value bool) {
	switch c.Map[option] {
	default:
		value = false
	case "yes", "on", "true":
		value = true
	}
	return
}

// Of the configurations, provided option, return the value as a string
func (c Config) GetString(option string) (value string) {
	value, _ = c.Map[option].(string)
	return
}

func (c *Config) Merge(other *Config) error {
	if other == nil {
		return nil
	}
	if other.Server {
		c.Server = other.Server
	}
	if len(other.Ip) > 0 {
		c.Ip = other.Ip
	}
	if len(other.Port) > 0 {
		c.Port = other.Port
	}
	if len(other.Port) > 0 {
		c.Port = other.Port
	}
	if len(other.DbHandler) > 0 {
		c.DbHandler = other.DbHandler
	}
	if len(other.MongoHost) > 0 {
		c.MongoHost = other.MongoHost
	}
	if len(other.MongoDbName) > 0 {
		c.MongoDbName = other.MongoDbName
	}
	if len(other.MongoUsername) > 0 {
		c.MongoUsername = other.MongoUsername
	}
	if len(other.MongoPassword) > 0 {
		c.MongoPassword = other.MongoPassword
	}
	if len(other.RemoteHost) > 0 && len(c.RemoteHost) == 0 {
		c.RemoteHost = other.RemoteHost
	}
	return nil
}

// Given a filename to a YAML file, unmarshal it, and return a Config
func ReadConfigFile(filename string) (*Config, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	config := Config{}
	if err = yaml.Unmarshal(bytes, &config); err != nil {
		return nil, err
	}

	return &config, nil
}

/*
func WriteConfigFile(filename string, data []byte) (err error) {
	return
}
*/