text:
%% -*- coding:utf-8 -*-
\chapter{Galois correspondence and first examples}
We state and prove the main theorem of these lectures: the Galois
correspondence. Then we start doing examples (low degree,
discriminant, finite fields, roots of unity).

\section{Some further remarks on normal extension. Fixed field}

Some definitions from previous lecture. $L$ over $K$ is
\mynameref{def:galoisextension} if and only if it is a
\mynameref{def:separableextension} and \mynameref{def:normalextension} or
in other words $L$ is a \mynameref{def:splittingfield} of a family of
separable irreducible polynomials over $K$. We also seen (see theorem
\ref{thm:lec5_4}) that in the case of finite extension
$\left[L:K\right] < \infty$ the number of automorphisms
$\left|Aut\left(L/K\right)\right| = \left[L:K\right]$.

There are several remarks on \mynameref{def:normalextension}s which show
that the extensions behave sometimes differently compare to other
types of extensions. Especially we have seen for that an extension
$L$ over $M$ over $K$ was finite or algebraic or separable or purely
inseparable if, and only if, it was true for $L$ over $M$ and $M$ over
$K$. So, for a normal extensions, this is not the case anymore.

\begin{remark}
  Let we have a tower of extensions $K \subset L \subset M$. If $M$ is
  normal over $K$ then of course the $M$ is normal over $L$. It is
  clear because if $M$ is a splitting field of a family of polynomials
  over $K$ the one can just consider them as being polynomials over
  $L$ and say that $M$ is a splitting field of a family of polynomials
  over $L$.

  But $L$ does not have to be normal over $K$ (see example
  \ref{ex:lec6_1}).
\end{remark}

\begin{example}
  Consider
  \[
  \mathbb{Q} \subset
  \mathbb{Q}\left(\sqrt[4]{2}\right)
  \subset
  \mathbb{Q}\left(\sqrt[4]{2}, i\right)
  \]

  We have $\mathbb{Q}\left(\sqrt[4]{2}, i\right)$ to be a splitting
  field for polynomial $X^4 -2$ but
  $\mathbb{Q}\left(\sqrt[4]{2}\right)$ is just a
  \mynameref{def:stemfield} (not \mynameref{def:splittingfield}) for this
  polynomial. And as result $\mathbb{Q}\left(\sqrt[4]{2}\right)$ is
  not a normal over $\mathbb{Q}$.
  \label{ex:lec6_1}
\end{example}

\begin{remark}
  A quadratic extension
  \footnote {
    Extensions with degree 2.
  }
  is normal. This is by formula for roots of a
  quadratic equation.
  \footnote {
    Because a if we have 2 roots $x_1, x_2 \in L \supset K$ then there
    exists the following relation $x_2 = k_1 + k_2 x_1$ where $k_1,
    k_2 \in K$. I.e. if we know one root then the other is easy
    computed and located in the same extension as the first one.
  }

  If $P$ quadratic over $K$ has 1 root in $L$ then its another root is
  also in $L$.
\end{remark}

\begin{remark}
  One often has $K \subset L \subset M$ with $L$ normal over $K$, $M$
  normal over $L$ but $M$ not normal over $K$ (see example
  \ref{ex:lec6_2}).
\end{remark}

\begin{example}
  Consider
  \[
  \mathbb{Q} \subset
  \mathbb{Q}\left(\sqrt{2}\right)
  \subset
  \mathbb{Q}\left(\sqrt[4]{2}\right)
  \]

  We have $\mathbb{Q}\left(\sqrt{2}\right)$ normal over $\mathbb{Q}$
  as well as $\mathbb{Q}\left(\sqrt[4]{2}\right)$ normal over
  $\mathbb{Q}\left(\sqrt{2}\right)$ because they both are quadratic
  extensions. But
  $\mathbb{Q}\left(\sqrt[4]{2}\right)$ is not normal over $\mathbb{Q}$
  (as it was mentioned in example \ref{ex:lec6_1})
  \label{ex:lec6_2}
\end{example}

We also seen at last lecture the following definition
(see definition \ref{def:setinvariants}):
\begin{definition}[Fixed field]
  If $L$ is a field and $G \subset Aut\left(L\right)$ then
  \[
  L^G = \left\{
  x \in L \mid \forall g \in G: g x = x
  \right\}
  \]
  is a fixed field
  \label{def:fixedfield}
\end{definition}

If we have a sub-field $K \subset L$ then we can consider the
following group of automorphisms of $L$ over $K$:
$Aut\left(L/K\right)$ in the case if $L$ is normal because otherwise
the group will be too small to give information
about $L$. But in the normal case it makes sense to consider
the group of automorphisms of $L$ over $K$.

We have seen (see (\ref{eq:lec5_2})) that if $L$ is separable over $K$
then
\[
L^{Aut\left(L/K\right)} = K
\]
This is because of the group of automorphisms was permuting the roots
over the minimal polynomial of $x$ over $K$ (see item
\ref{rem:item:lec5_onnormalext_3} in remark
\ref{rem:lec5_onnormalext}).

We also have seen (see theorem \ref{thm:artin}) that if $G$ is finite
the $L$ is \mynameref{def:galoisextension} over $L^G$ and
$\left[L:L^G\right] = \left|G\right|$.

And now we are going to summarize all these in a theorem which is in
fact the main subject of this lecture course and this theorem is
called the Galois correspondence.

\section{The Galois correspondence}

Let $L$ over $K$ be a \mynameref{def:galoisextension}. By definition the
group automorphisms $Aut\left(L/K\right)$ is called
\mynameref{def:galoisgroup} and denoted as $Gal\left(L/K\right)$
\begin{theorem}[Galois correspondence]
  \label{thm:galoiscorrespondence}
  There are several statements:
  \begin{enumerate}
  \item If $L$ is finite over $K$ then there is a
    \mynameref{def:bijection} between a sub-extension $F$
    ($K \subset F \subset L$) and a subgroup $H \subset
    Gal\left(L/K\right)$. The correspondence is the following
    \begin{eqnarray}
      F \rightarrow Gal\left(L/F\right)
      \nonumber \\
      L^H \leftarrow H
      \nonumber
    \end{eqnarray}
  \item The following statement are equivalent (if and only if)
    \begin{enumerate}
    \item $F$ is Galois over $K$ \label{thm:galoiscorrespondence:item2a}
    \item $\forall g \in Gal\left(L/K\right) g\left(F\right) = F$
      \label{thm:galoiscorrespondence:item2b}
    \item $Gal\left(L/F\right)$ is a \mynameref{def:normalsubgroup} in
      $Gal\left(L/K\right)$
    \end{enumerate}
    In this case  $g$ goes to $g$ restricted to $F$: $g \to
    \left.g\right|_F$ this is a \mynameref{def:surjection}
    $Gal\left(L/K\right) \twoheadrightarrow Gal\left(F/K\right)$ and
    the kernel is $Gal\left(L/F\right)$.
    \footnote{
      The fact is explained at the end of the proof of the theorem and
      is used in the claim \ref{claim:galoisquotient} validation.
    }
  \end{enumerate}
  \begin{proof}
    \begin{enumerate}
    \item Most work have been done before. What have we got by now?
      $L^{Gal\left(L/F\right)} = F$ (see (\ref{eq:lec5_2})). We also
      have $H \subset Gal\left(L/L^H\right)$.
      \footnote{
        Ekaterina called the fact obvious but let try to explain it.
        From (\ref{eq:lec5_2}) we have
        $L^{Gal\left(L/L^H\right)} = L^H$ thus
        $\forall h \in H$ it should also satisfy $h \in
        Gal\left(L/L^H\right)$ therefore $H \subset
        Gal\left(L/L^H\right)$.
      }
      \mynameref{thm:artin} gives us
      $\left[L:L^H\right] = \left|H\right|$ but with theorem
      \ref{thm:lec5_4} we also have
      $\left[L:L^H\right] = \left|Gal\left(L/L^H\right)\right|$ so one
      must have $H = Gal\left(L/L^H\right)$ as soon as the subset $H$
      has the same cardinality as the set $Gal\left(L/L^H\right)$ itself.

      This means that the maps that we have in the theorem :
      $F \rightarrow Gal\left(L/F\right)$ and
      $L^H \leftarrow H$ are mutually inverse
      \footnote{
        We have the following maps:
        \[
        F \to Gal\left(L/F\right) \to L^{Gal\left(L/F\right)} = F
        \]
        I.e. $\forall F$ such that $K \subset F \subset L$ we can
        construct $H = Gal\left(L/F\right)$ then we can construct
        $L^H$ such that (by theorem \ref{thm:artin})
        $K \subset L^H \subset L$.
      }
      and if a map is invertible then there is a \mynameref{def:bijection}.
    \item We should proof equivalence of the following statements:
      \begin{enumerate}
      \item $F$ is Galois over $K$ \label{item:galoiscorrespondence1}
      \item $\forall g \in Gal\left(L/K\right), g\left(F\right) = F$
        \label{item:galoiscorrespondence2}
        \footnote{
          $g \in Gal\left(L/K\right)$ operates on $L \supset F$.
        }
      \item $Gal\left(L/F\right) \triangleleft Gal\left(L/K\right)$
        \label{item:galoiscorrespondence3}
      \end{enumerate}
    \end{enumerate}

    Lets show that \ref{item:galoiscorrespondence1} implies
    \ref{item:galoiscorrespondence2}. Fix $x \in F$ then the minimal
    polynomial $P_{min}\left(x, K\right)$ splits in $L$ but it has a
    root in $F$, thus it should have all roots in $F$ by normality.
    I. e. as soon as $F$ is a \mynameref{def:normalextension},
    $P_{min}\left(x, K\right)$ splits in $F$ (see theorem
    \ref{thm:lec5_3}). This means, of course,
    that any map from Galois group preserves $F$ since it premutes the
    roots: $\forall g \in Gal\left(L/K\right)$ $g$ permutes the roots
    of $P_{min}\left(x, K\right)$ and that is the true for any $x \in
    F$ therefore $g\left(F\right) \subset F$ since $F$ is generated
    (consists of) such roots.
    \footnote{
      We have the following fact: $x \in F$ then also $g(x) \in F$
      i.e. $g(F) \subset F$. For equality $g\left(F\right) = F$ we
      have to proof that $\forall g \in Gal\left(L/K\right): F \subset
      g\left(F\right)$. Really let $g \in Gal\left(L/K\right)$ then
      $g^{-1} \in Gal\left(L/K\right)$ and
      $g^{-1}(F) \subset F$ therefore $F = id(F) =
      g\left(g^{-1}(F)\right) \subset
      g(F)$ i.e. $F \subset g(F)$.
    }

    Lets show that \ref{item:galoiscorrespondence2} implies
    \ref{item:galoiscorrespondence1}. If $g\left(F\right) \subset F$
    then all roots of $P_{min}\left(x, K\right)$, $x \in F$, are in $F$
    since $g$ permutes those roots or, in other words, since Galois
    group acts transitively on
    roots of an irreducible polynomial
    \footnote{
      see also 2d remark \ref{rem:lec5_onnormalext} that says that if
      $F$ is normal then $Gal(L/F)$ acts
      transitively on the roots of any irreducible polynomial $P \in
      F\left[X\right]$.
    }
    therefore $F$ is normal by
    definition.
    \footnote{
      More clear explanation is below. We have to prove that $F$ is
      normal and separable. Normality: $\forall P_{min}\left(x,
      K\right)$ splits in $F$ thus the theorem \ref{thm:lec5_3} gives
      us the required normality. About separability. We have $K
      \subset F \subset L$. $L$ is separable over $K$ as soon as $L$
      is Galois extension. Thus theorem \ref{thm:lec3_3} gives us $F$
      separability.
    }

    Lets show that \ref{item:galoiscorrespondence1} and
    \ref{item:galoiscorrespondence2} are equivalent to
    \ref{item:galoiscorrespondence3} i.e. let $g \in G$,
    $g\left(F\right) \subset L$ then if
    $h \in Gal\left(L/F\right)$ is such that $\left.h\right|_F = id$
    then $\left.g h g^{-1}\right|_{g\left(F\right)} = id$.
    \footnote{
      The map $g^{-1}$ acts as follows $g^{-1}: g(F) \to F$ i.e. $h$
      in $\left.g h g^{-1}\right|_{g\left(F\right)}$ operates on $F$
      only therefore
      \[
      \left.g h g^{-1}\right|_{g\left(F\right)} =
      \left.g h_F g^{-1}\right|_{g\left(F\right)}  =
      \left.g g^{-1}\right|_{g\left(F\right)} = id
      \]
    }
    This means
    that $g h g^{-1} \in Gal\left(L/g\left(F\right)\right)$ (see
    (\ref{eq:lec5_2})) so the
    statement $g\left(F\right) = F$ is the same to say
    \[
    g Gal\left(L/F\right) g^{-1} = Gal\left(L/F\right)
    \]
    So apply this to all $g \in Gal\left(L/K\right)$ one can get that
    $Gal\left(L/F\right)$ is a \mynameref{def:normalsubgroup} of
    $Gal\left(L/K\right)$ by the definition of
    \mynameref{def:normalsubgroup}.

    Finally if all this statements
    (\ref{item:galoiscorrespondence1}
    $\Longleftrightarrow$
    \ref{item:galoiscorrespondence2}
    $\Longleftrightarrow$
    \ref{item:galoiscorrespondence3}
    ) are true then we can consider map (make sense by
    \ref{item:galoiscorrespondence2})
    \[
    \phi: Gal\left(L/K\right)
    \xrightarrow[g \to \left.g\right|_F]{}
    Gal\left(L/F\right).
    \]
    This is a \mynameref{def:surjection} by theorem \ref{thm:lec2_3}
    \footnote{
      We have that $\forall g_F \in Gal\left(L/F\right)$ $g_F$ is a
      homomorphism that operates as follows $g_F: F \to \bar{K}$
      (note that by the theorem \ref{thm:lec5_3} all homomorphisms on
      a normal extension $F$ have the same image namely $F$)
      and
      therefore it can be extended (by theorem
      \ref{thm:lec2_3}) to homomorphism $g: L \to \bar{K}$
      i.e. $\forall g_F \in  Gal\left(L/F\right), \exists g \in
      Gal\left(L/K\right)$ such that $\phi(g) = g_F$. Or in other
      words $\phi$ is a \mynameref{def:surjection}.
    }
    and the kernel $\ker \phi = Gal\left(L/F\right)$ by
    definition because the kernel consists of things which are identity on $F$.
  \end{proof}
\end{theorem}

\begin{remark}
  If $L$ over $K$ is not finite then Galois correspondence is not
  \mynameref{def:bijection} i.e. the maps which are in the theorem still
  make sense, but they will not be mutually inverse bijections and we
  shall see an example (see section \ref{sec:lec6_finitefield} about it).
  \label{rem:lec6_gcnotbijection}
\end{remark}

\section{First examples (polynomials of degree 2 and 3)}

\begin{example}[Degree 2]
  Let $\left[L:K\right] = 2$ and $char K \ne 2$. The extension $L$ is
  generated by a root of
  quadratic polynomial i.e. $x \in L \setminus K$ then
  $P_{min}\left(x, K\right)$ is quadratic and if we look at the
  formula for the root of the equation we will see that the extension
  is generated by a root of discriminant $\Delta$:
  $L = K\left(\sqrt{\Delta}\right)$.

  What can we say about the $Gal\left(L/K\right)$. It consists of 2
  elements and there is only one cyclic group of 2 elements
  \footnote{
    There is only one group of 2 elements \cite{wiki:finitegroup}
  }
  :
  $\mathbb{Z}/2\mathbb{Z}$. Therefore
  \[
  Gal\left(L/K\right) \cong \mathbb{Z}/2\mathbb{Z}.
  \]
  The elements of the group is identity and an element that exchanges
  the 2 roots i.e. permutes $\sqrt{\Delta}$ and $-\sqrt{\Delta}$.
\end{example}

\begin{example}[Degree 3]
    Let $\left[L:K\right] = 3$ and $char K \ne 3$ (separable
    extensions) then $L$ is generated by $x$ - root of
    degree 3 polynomial $P$ and there are 2 cases
    \begin{enumerate}
    \item $P$ splits in $L$ therefore $L$ is a Galois extension and
      $Gal\left(L/K\right)$ is the Galois group but the
      Galois group of 3 elements must be cyclic
      \footnote{
        There is only one group of 3 elements
        and it is cyclic \cite{wiki:finitegroup}.
      }
      i.e.
      $Gal\left(L/K\right) \cong \mathbb{Z}/3\mathbb{Z}$ - cyclic
      group of order 3.
    \item $P$ does not split in $L$ then there exists
      $M = K\left(x_1, x_2, x_3\right)$ - splitting field where
      $x_{1,2,3}$ are roots of $P$ and $L = K\left(x_1\right)$. $M$ is
      Galois extension and the Galois group is embeded into a group of
      permutation of 3 elements (because Galois group permutes the roots):
      $Gal\left(M/K\right) \hookrightarrow S_3$.

      As soon $L \subsetneq M$ then $\left[M:K\right] > 3$ so
      $Gal\left(M/K\right) = S_3$. In particular
      $\left[M:K\right] = \left|S_3\right| = 6$
    \end{enumerate}

    If you see a cubic polynomial how will you decide is its Galois
    group is cyclic or $S_3$? This is determined by a
    \mynameref{def:discriminant} of polynomial which is a subject of
    next section (see example \ref{ex:lec6_discriminant3degree}
    and proposition \ref{prop:lec6_1}).

    \label{ex:lec6_degree3}
\end{example}

\section{Discriminant. Degree 3 (cont'd). Finite fields}

\subsection{Discriminant}

\begin{definition}[discriminant]
  Let $P \in K\left[X\right]$. The polynomial has the following roots
  in $\bar{K}$: $x_1, x_2, \dots, x_n$. The following product is
  called discriminant:
  \[
  \Delta = \prod_{i < j} \left(x_i - x_j\right)^2
  \]
  \label{def:discriminant}
\end{definition}

If we take group $G = Gal\left(P\right)$ then
$G \subset S_n$ and any permutation preserves $\Delta$ and as result
we have $\Delta \in K$ (see (\ref{eq:lec5_2})).

Lets take a root of discriminant (we have to choose some roots order
for this operation) then
\[
\sqrt{\Delta} = \prod_{i < j} \left(x_i - x_j\right)
\]
this quantity is preserved only by even
\footnote{
  You can see from definition \ref{def:paritypermutation} and example
  \ref{ex:paritypermutation} that for even permutations each insertion
  is equivalent to a root exchange. If the number of such exchange is
  even then we can return the changed root of a discriminant to its original
  form with event steps. Each step changes the sign and as result the
  even steps will not change the sign.
}
(and not by odd) permutations.

\begin{proposition}
  Let $G = Gal\left(P\right)$ - \mynameref{def:galoisgroup} then $G
  \subset A_n$
  \footnote {
    $A_n$ is a group of even permutations
  }
  if and only if $\sqrt{\Delta} \in K$.
  \begin{proof}
    Since if the Galois group is even then, this will be preserved by
    an element of Galois group and so will be in $K$ and conversely, if
    it is an element of $K$, then it must be preserved by the Galois
    group, but we know it is preserved only by even permutations.
  \end{proof}
  \label{prop:lec6_1}
\end{proposition}

If we return to our example \ref{ex:lec6_degree3} we can get the
following one
\begin{example}[Discriminant of polynomial degree 3]
  Lets compute the discriminant for the following polynomial:
  $X^3 + p X + q$.
  \footnote {
    $X^2$ element can be always hidden via a variable change. Thus the
    polynomial can be considered as a common case for cubic polynomials.
  }

  The discriminant easy to compute:
  \footnote{
    The below explanation was taken from
    \cite{mathstackexchange:discriminant3}.
    The discriminant is a polynomial of degree 6. $p$ can be
    represented as a polynomial of degree 2. $q = - X^3 - p X$ is a
    polynomial of degree 3. The discriminant therefore can be
    represented as follows $\Delta = a p^3 + b q^2$ where $a,b$ are
    numbers. Let $p = -1, q = 0$ then the polynomial $X^3 - X$ has 3
    roots: $-1, 0, 1$. It is easy to compute discriminant
    $\Delta = (0 + 1)^2(0 - 1)^2(1+1)^2 = 4$ therefore $a =  -4$.
    For the case $p = 0, q = -1$ we will get the polynomial $X^3 - 1$
    with roots $1, \zeta, \zeta^2$. We also have
    \[
    \zeta^2 + \zeta + 1 = 0
    \]
    therefore
    \[
    \left(\zeta - 1\right)^2 = \zeta^2 - 2 \zeta + 1 = - 3 \zeta
    \]
    and
    \[
    \left(\zeta + 1\right)^2 = \zeta^2 + 2 \zeta + 1 =  \zeta
    \]
    thus
    \begin{eqnarray}
    \Delta = \left(\zeta - 1\right)^2\left(\zeta^2 -
    1\right)^2\left(\zeta^2 - \zeta\right)^2 =
    \nonumber \\
    = \left(\zeta - 1\right)^2 \left(\zeta - 1\right)^2
    \left(\zeta + 1\right)^2 \zeta^2 \left(\zeta - 1\right)^2 =
    \nonumber \\
    = \left(- 3 \zeta\right)^3 \zeta^3 = -27.
    \nonumber
    \end{eqnarray}
    As result $b=-27$.
  }
  \(
  \Delta = -4 p^3 - 27 q^2
  \).
  So if $\Delta$ is a square in $K$ then $Gal\left(P\right) \cong A_3$
  (cyclic of order 3)
  \footnote{
    See example \ref{ex:s3group} about groups $S_3$ and
    \mynameref{def:alternatinggroup} $A_3$.
  }
  . If not then $Gal\left(P\right) \cong S_3$ (non
  commutative group of 6 elements).

  What can we say about sub-extensions for the two cases? Let $M$ is a
  splitting field of $P$ over $K$ then for the first case there is no
  any sub-extension. For the second case there are several
  sub-extensions (they are determined by sub-groups of the Galois
  group: $S_3$ for our case). Especially we have 3 sub-extension of
  degree 3:
  \footnote{
    because $x_1, x_2, x_3$ are roots of a cubic polynomial
  }
  $K\left(x_1\right)$, $K\left(x_2\right)$ and
  $K\left(x_3\right)$, fixed by non-normal sub-groups of order 2 -
  because $M$ is degree 2 over $K\left(x_{1,2,3}\right)$.
  \footnote{
    $K\left(x_i\right) = M^{Gal\left(M/K\left(x_i\right)\right)}$ and
    $Gal\left(M/K\left(x_i\right)\right)$ has order 2, as soon as
    $\left[M:K\left(x_i\right)\right] = 2$,
    i.e.
    $Gal\left(M/K\left(x_i\right)\right) \cong \mathbb{Z}/2\mathbb{Z}$
    - transposition of roots
  }
  And we have
  one quadratic sub-extension
  (of degree 2) fixed by $A_3 \subset S_3$ this is
  $K\left(\sqrt{\Delta}\right)$.
  \footnote{
    The extension should be $K\left(\alpha\right)$ where $\alpha$ is a
    root of a quadratic polynomial and $\alpha \notin
    K$ but $\alpha \in M$. $\sqrt{\Delta}$ is a good choice for the
    sub-extension
    generator because $\sqrt{\Delta} \notin K$ but $\sqrt{\Delta} \in
    M$ and $\sqrt{\Delta}$ - is a root of a quadratic polynomial
    i.e. it generates a quadratic extension. In the case
    $K\left(\sqrt{\Delta}\right) =
    M^{Gal\left(M/K\left(\sqrt{\Delta}\right)\right)} = M^{A_3}$ i.e.
    $Gal\left(M/K\left(\sqrt{\Delta}\right)\right) = A_3$.
  }

  \mynameref{thm:galoiscorrespondence} says us that there are no other
  sub-extensions. Because those sub extensions correspond objectively
  to subgroups of the \mynameref{def:galoisgroup}. And in this case, it
  does not have so many subgroups. These are just three subgroups of order 2
  generated by transpositions, and one subgroup of order 3 generated
  by a three cycle.
  \label{ex:lec6_discriminant3degree}
\end{example}

\subsection{Finite fields. An infinite degree example}
\label{sec:lec6_finitefield}
We have seen that theory of finite fields is easy. Especially all
\mynameref{def:galoisgroup}s are cyclic (see corollary
\ref{cor:lec3_2}). I.e. we have the field $\mathbb{F}_{p^n}$ over
$\mathbb{F}_{p}$. The Galois group is cyclic and generated by
Frobenius map (see remark \ref{rem:frobeniushomomorphism}) which is
$F_p: x \to x^p$.

More interesting are infinite extensions of a finite field, for
instance the \mynameref{def:algebraicclosure}.
Thus consider $\bar{\mathbb{F}}_p$ as an extension of
$\mathbb{F}_p$. If we take an invariant generated by Frobenius $F_p$
\footnote {
  The group generated by one element $F_p$ is denoted as $\left<F_p\right>$.
}
then
\footnote{
  It required some explanation. $\left<F_p\right>$ consists of powers
  of Frobenius map: $F_p, F_{p^2}, \dots, F_{p^n}, \dots$, we also
  have that $\bar{\mathbb{F}}_p^{F_{p^n}} = \mathbb{F}_{p^n}$
  (This is because $\forall x \in \mathbb{F}_{p^n}:
  F_{p^n}\left(x\right) = x^{p^n} = x$). Therefore
  \[
  \bar{\mathbb{F}}_p^{\left<F_p\right>} =
  \cap_n \mathbb{F}_{p^n} = \mathbb{F}_p
  \]
}
\[
\bar{\mathbb{F}}_p^{\left<F_p\right>} = \mathbb{F}_p
\]
but
\[
Gal\left(\bar{\mathbb{F}}_p/\mathbb{F}_p\right) \ne
\left<F_p\right>
\]
therefore there is no bijective correspondence between sub-fields and
sub-groups. In particular the \mynameref{thm:galoiscorrespondence} is
not \mynameref{def:bijection} (as it was mentioned at remark
\ref{rem:lec6_gcnotbijection})

So how to see that the Galois group is not cyclic:
$Gal\left(\bar{\mathbb{F}}_p/\mathbb{F}_p\right) \ne
\left<F_p\right>$?

Really a smaller group is not cyclic.
\footnote{
  We have a theorem that a subgroup of a cyclic group is cyclic
  (see \mynameref{thm:fundamentaltheoremofcyclicgroup}).
  This
  means that if the whole group is cyclic then the smaller group has
  to be a cyclic too.
}
Lets look at the following:
\[
\mathbb{F}_p \subset \mathbb{F}_{p^2} \subset \dots
\mathbb{F}_{p^{2^n}} \subset \dots
\]
and let
\[
L = \cup \mathbb{F}_{p^{2^n}}
\]
We claim that $Gal\left(L/\mathbb{F}_p\right)$ is not cyclic. Consider
the following number $a_n = 1+ 2 + 4 + \dots + 2^n$ then
$\forall x \in \mathbb{F}_{p^{2^n}}$
\begin{equation}
  F_p^{a_n}\left(x\right) = F_p^{a_m}\left(x\right)
  \label{eq:lec6_finitefieldinfinite1}
\end{equation}
for any $m > n$.
\footnote{
  If $F_p^{2^{n+l}} = id$ (see below in the text) then
  \begin{eqnarray}
  F_p^{a_m}\left(x\right) = F_p^{a_n + 2^{n + 1} + 2^{n+2} + \dots +
    2^m}\left(x\right) =
  \nonumber \\
  = F_p^{a_n}\left(F_p^{2^{n + 1} + 2^{n+2} + \dots +
    2^m}\left(x\right)\right) =
  F_p^{a_n}\left(id\left(x\right)\right) =
  F_p^{a_n}\left(x\right).
  \nonumber
  \end{eqnarray}
}
This is because the Frobenius map $F_p$ sends $x$ to $x^p$ is an
identity on $\mathbb{F}_p$ therefore $F_p^{2^{n+l}}$ is identity on
$\mathbb{F}_{p^{2^n}}$ $\forall l \ge 0$.
\footnote{
  For example consider $F_p^{2^{n+1}}$ and let $x \in x
  \in \mathbb{F}_{p^{2^n}}$. We have
  \begin{eqnarray}
  F_p^{2^{n+1}}\left(x\right) =
  F_p^{2^n \cdot 2}\left(x\right) =
  F_p^{2^n + 2^n}\left(x\right) =
  \nonumber \\
  =
  F_p^{2^n}\left(F_p^{2^n}\left(x\right)\right) =
  F_p^{2^n}\left(x^{2^n}\right) =
  F_p^{2^n}\left(x\right) = x^{2^n} = x.
  \nonumber
  \end{eqnarray}
}
This implies
that
there exists an automorphism $\phi: L \to L$ such that
$\forall n \ge 0$
\footnote{
  ??? We can say that $\phi$ maps $L$ to $L$. If equation
  (\ref{eq:lec6_finitefieldinfinite}) holds for an arbitrary large $N$
  (i.e. informally $\mathbb{F}_{p^{2^N}}$ very
  close  to $L$)
  then it also holds $\forall n < N$ because
  (\ref{eq:lec6_finitefieldinfinite1})
}
\begin{equation}
  \left.\phi\right|_{\mathbb{F}_{p^{2^n}}} = F^{a_n}
  \label{eq:lec6_finitefieldinfinite}
\end{equation}
but $\forall k \in \mathbb{Z}$ $F_p^k \ne \phi$.
\footnote{
  i.e. $\phi \notin \left<F_p\right>$
}
One can look at
$\phi$ as $\phi = F_p^{1+2+4+ \dots + 2^n + \dots}$ but this is, of
course, very informal.
\footnote{
  Using (\ref{eq:lec6_finitefieldinfinite}) ``informally'' one can get
  \[
  \phi = \left.\phi\right|_L =
  \lim_{n \to \infty}\left.\phi\right|_{\mathbb{F}_{p^{2^n}}} =
  \lim_{n \to \infty} F^{a_n} =
  F^{1
    +2 +4 + \dots + 2^n + \dots}
  \]
}
The rigorous conclusions we can draw from this
is that our Galois group is not a cyclical group generated by the
Frobenius map i.e.
$Gal\left(\bar{\mathbb{F}}_p/\mathbb{F}_p\right) \ne
\left<F_p\right>$. And also, that we don't have a bijective Galois
correspondents like we have for finite field extensions i.e no
bijective correspondents  between sub-groups
of the Galois group and sub-extensions. Indeed the fixed field of the
$F_p$ and and the whole Galois group coincide.

\section{ Roots of unity: cyclotomic polynomials}
Consider a number $n$ that is prime to
\mynameref{def:fieldcharacteristic} of $K$:
$\left(n, char\left(K\right)\right) = 1$ and consider the polynomial
$P_n = X^n - 1$ (if $\left(n, char\left(K\right)\right) = 1$
then the
polynomial has no multiple roots)
\footnote{
 if $\left(n, char\left(K\right)\right) = 1$ then $P_n' = n X^{n-1}
 \not \equiv 0 \mod char\left(K\right)$ and as result
 $gcd\left(P_n, P_n'\right) = 1$ i.e. $P_n$ does not have multiple
 roots.
}
. Thus the polynomial has exactly $n$
roots which form a cyclic (see definition\ref{def:cyclicgroup})
multiplicative subgroup of $\bar{K}^\times$
(see definition \ref{def:multiplicativegroup})
\footnote{
  $\exists x \in \mu_n$ such that $x^n = 1$ i.e. $x$ is a root of $P_n$.
}
denoted by $\mu_n$. So $\mu_n$ is just the group of $n$ roots of unity
in $\bar{K}^\times$.

\begin{definition}[Primitive roots of unity]
  There are root of unity of degree $n$ such that not root of unity of
  degree $d < n$.
  \label{def:primitiverootsofunity}
\end{definition}

The set of \mynameref{def:primitiverootsofunity} is denoted as
$\mu_n^*$. All elements of $\mu_n$ are powers of a single one:
$\forall x \in \mu_n, \exists a \in \mathbb{N}: x = \zeta^a$ for some
$\zeta \in \mu_n$. And primitive roots of unity form the following set
$\left\{\zeta^a\right\}$ where $\left(a, n\right) = 1$.
\label{sec:lec6_5_primitiveroot}
\footnote{
  The fact require a proof. Consider case $\left(a, n\right) = k >
  1$. Thus $\frac{n}{k}, \frac{a}{k} \in \mathbb{Z}$ and we can
  get
  \[
  \left(\zeta^a\right)^{\frac{n}{k}} =
  \left(\zeta^{\frac{a}{k}}\right)^n = 1
  \]
  therefore $\zeta^a$ is a root of $X^{\frac{n}{k}} - 1$ and as soon
  as $\frac{n}{k} < n$ we conclude that $\zeta^a \notin \mu_n^\ast$
  (but $\zeta^a \notin \mu_n$) i.e. $\zeta^a$ is not a
  \mynameref{def:primitiverootsofunity}.
}
The number of
such primitive roots is determined by \mynameref{def:eulerfuction}:
$\left|\mu_n^*\right| = \phi\left(n\right)$.
\footnote{
  That is by definition of \mynameref{def:eulerfuction} that counts the
  positive integers up to a given integer $n$ that are relatively
  prime to $n$
}

\begin{definition}[$n$-th cyclotomic polynomial]
  The polynomial
  \[
  \Phi_n = \prod_{\alpha \in \mu_n^*}\left(X - \alpha\right) \in \bar{K}\left[X\right]
  \]
  is called $n$-th cyclotomic polynomial.
  \label{def:cyclotomicpolynomial}
\end{definition}

\begin{example}[$n$-th cyclotomic polynomial]
  \[
  \Phi_1 = X - 1
  \]
  \[
  \Phi_2 = \frac{X^2 - 1}{X-1} = X + 1
  \]
  \[
  \Phi_3 = \frac{X^3 - 1}{X-1} = X^2 + X + 1
  \]
  \[
  \Phi_4 = \frac{X^4 - 1}{\left(X-1\right)\left(X + 1\right)} = X^2 + 1
  \]
  \[
  \Phi_5 = X^4 + X^3 + X^2 + 1
  \]
\end{example}

\begin{gapexample}[Cyclotomic polynomial]
  There are several ways to get a \nameref{def:cyclotomicpolynomial}
  in GAP \cite{url:gap}. Consider 7th cyclotomic polynomial.

  We can use the fact that
  $\Phi_7 = P_{min}\left(\zeta_7,\mathbb{Q}\right)$:
  \begin{verbatim}
    gap> x:=Indeterminate(Rationals,"x");;
    gap> zeta:=E(7);;
    gap> MinimalPolynomial(Rationals, zeta);
    x^6+x^5+x^4+x^3+x^2+x+1
    gap>
  \end{verbatim}
  I.e. $\Phi_7 = P_{min}\left(\zeta_7,\mathbb{Q}\right) =
  X^6+X^5+X^4+X^3+X^2+X+1$.

  Another way to get the same answer is
  \begin{verbatim}
    gap> x:=Indeterminate(Rationals,"x");;
    gap> CyclotomicPolynomial(Rationals,7);
    x^6+x^5+x^4+x^3+x^2+x+1
  \end{verbatim}
\end{gapexample}

\begin{proposition}
  \begin{enumerate}
    \item
      \(
      P_n = \prod_{d \mid n} \Phi_d
      \)
    \item $\Phi_n$ has coefficients in \mynameref{def:primefield}s:
      $\mathbb{Q}$ if $char K = 0$ or
      $\mathbb{F}_p$ if $char K = p$
    \item If $char K = 0$ then $\Phi_n \in
      \mathbb{Z}\left[X\right]$. If $char K = p$ then $\Phi_n$ is the
      reduction $\mod{p}$ of the \mynameref{def:cyclotomicpolynomial}
      over $\mathbb{Z}$.
  \end{enumerate}
  \begin{proof}
    The proof was marked as an exercise in the lectures

    The first item proof is the following. The $X^n - 1$ has $n$ roots and
    lets $\zeta$ is one of the
    root. Let $d=ord\left(\zeta\right)$ i.e. $\zeta^d = 1$ from other side
    $\zeta^n = 1$ i.e. $d \mid n$. Therefore $\zeta \in \mu_d^\ast$
    i.e. $\zeta$ is a root of $\Phi_d$. Thus any root $X^n - 1$ will
    also be a root of $\prod_{d \mid n} \Phi_d$.
    From other side for any root $\zeta'$ of $\prod_{d \mid n}
    \Phi_d$ exists $d$ such that $\zeta'$ will be a root of $\Phi_d$
    and as soon as $d \mid n$ then $\exists l \in \mathbb{Z}: n = d
    \cdot l$ therefore $\left(\zeta'\right)^n =
    \left(\left(\zeta'\right)^d\right)^l = 1$ i.e. $\zeta'$ is also
    a root of $X^n - 1$. The both polynomial
    are \mynameref{def:monicpolynomial}s and therefore are the same.

    Lets consider case
    $char(K) = 0$ (for the second and third parts) and lets proof that
    in the case $\Phi_d$ has coefficients in
    $\mathbb{Z}$. Lets proof by induction. The case $n$ is trivial
    because
    $\Phi_1 = X - 1$. Let for any $d < n$ we have that $\Phi_d$ has
    integer coefficients. Then using
    \[
    P_n = \prod_{d \mid n} \Phi_d
    \]
    we can get
    \[
    \Phi_n = \frac{X^n-1}{\prod_{d \mid n, d \ne n} \Phi_d}
    \]
    using the fact that $\prod_{d \mid n, d \ne n} \Phi_d$ has integer
    coefficients (by induction hypothesis) we can conclude that
    $\Phi_n$ has coefficients in $\mathbb{Q}$. Then using
    \mynameref{lem:gauss} we can conclude that $\Phi_n \in
    \mathbb{Z}\left[X\right]$.

    Finally using
    \[
    P_n = X^n - 1 = P_n \mod p = \prod_{d \mid n} \left(\Phi_d \mod p\right)
    \]
    one can conclude that if $char K = p$ then $\Phi_n$ is the
    reduction $\mod{p}$ of the \mynameref{def:cyclotomicpolynomial}
    over $\mathbb{Z}$.

  \end{proof}
  \label{prop:lec6_cyclotomic}
\end{proposition}

\section{Irreducibility of cyclotomic polynomial.The Galois group}

\begin{theorem}
  Let $char(K) = 0$, then $\Phi_n$ is irreducible in
  $\mathbb{Q}\left[X\right]$
  (it amounts to the same to say that this is irreducible in
  $\mathbb{Z}\left[X\right]$ as we know).
  \begin{proof}
    We have to prove that all \mynameref{def:primitiverootsofunity} have
    the same minimal polynomial over $\mathbb{Q}$. It must be $\Phi_n$
    by degree reason.

    Let fix one primitive root $\zeta$ and all others have the form
    $\zeta^a$ where $a$ is prime to $n$: $\left(a,n\right)=1$.
    \footnote{
      as it was mentioned at the section \ref{sec:lec6_5_primitiveroot}.
    }
    If we
    can show these for $a$
    prime then we can also show this for all $a$.
    \footnote{
      Let $a = l \cdot k$ where $l$ and $k$ are prime. We have (as it
      will be proved later) that $\nu = \zeta^l$ and $\zeta$ are roots of the
      same minimal polynomial. $\nu^k$ will also be a root of that
      minimal polynomial (if $\nu$ is a root and $k$ is prime than
      $\nu^k$ will also be a root of the same polynomial), but
      $\nu^k = \zeta^{k \cdot l} = \zeta^a$.
    }
    Thus we may
    assume that $a$ is a prime number $l$
    and suppose
    \[
    P_{min}\left(\zeta, \mathbb{Q}\right)
    \ne
    P_{min}\left(\zeta^l, \mathbb{Q}\right).
    \]
    Then $\Phi_n = f \cdot g$ where $f$ has $\zeta$ as a root and $g$
    has $\zeta^l$ as a root. This is true in
    $\mathbb{Q}\left[X\right]$ but also as we seen
    \footnote{
      $\Phi_n \in \mathbb{Z}\left[X\right]$ (see proposition
      \ref{prop:lec6_cyclotomic}). \mynameref{lem:gauss} says that
      if $\Phi_n$ is reducible than they factors are also in
      $\mathbb{Z}\left[X\right]$.
    }
    in
    $\mathbb{Z}\left[X\right]$. So we have $g\left(\zeta^l\right) = 0$
    thus we can define $g_l\left(X\right) = g\left(X^l\right)$ then
    $g_l$ will have $\zeta$ as a root. But $g_l \equiv g^l \mod l$.
    \footnote{
      Using $g\left(X\right) = a_n X^n + \cdots + a_1 X + a_0$ we can get
      \begin{eqnarray}
        g^l\left(X\right) = \left(a_n X^n + \cdots + a_1 X +
        a_0\right)^l =
        \nonumber \\
        = a_n {X^l}^n + \cdots + a_1 {X^l} +
        a_0 + l \cdot \left( \dots \right) \equiv g_l \mod l
        \nonumber
      \end{eqnarray}
    }
    Thus in
    modulo $l$ $\Phi_n$ has $\zeta$ as a multiple root. This is
    impossible because $\Phi_n$ divides $P_n$ and this does not have
    multiple roots whenever $l$ prime to $n$.
  \end{proof}
  \label{thm:lec6_2}
\end{theorem}

\begin{remark}
  Statements of theorem \ref{thm:lec6_2} are not true if $char(K) >
  0$. I.e. over $\mathbb{F}_p$ $\Phi_n$ is not always irreducible.

  For instance $\Phi_8 = X^4 + 1$ is reducible over $\mathbb{F}_p$ for
  any $p$. For instance $p = 2$
  \footnote{
    $1$ is a root because $1^4 + 1 = 2 \equiv 0 \mod 2$. Therefore
    $\Phi_8 = X^4 + 1$ is reducible over $\mathbb{F}_2$
  }
  In fact it splits in $\mathbb{F}_{p^2}$.
  This is because if $p$ is odd then $8\mid p^2-1$ so the
  \mynameref{def:multiplicativegroup}
  $\mathbb{F}_{p^2}^\times$ contains a cyclic subgroup of order 8 which is
  exactly the group of 8 roots of unity.
\end{remark}

The main theorem about cyclotomic extensions is the following
\begin{theorem}
  The splitting field $L$ of $P_n$ over $K$ is $K\left(\zeta\right)$,
  where $\zeta$ is a root of $\Phi_n$.

  $\forall g \in Gal\left(L/K\right)$ acts by $g: \zeta \to
  \zeta^{a_g}$ where $\left(a_g, n\right) = 1$.

  $Gal\left(L/K\right)  \hookrightarrow
  \left(\mathbb{Z}/n\mathbb{Z}\right)^\times$ and this is an isomorphism
  whenever $\Phi_n$ is irreducible over $K$ (for example $K
  =\mathbb{Q}$).
  \begin{proof}
    \begin{enumerate}
      \item All $n$-th roots of unity are powers of $\zeta$ so they
        are in  $K\left(\zeta\right)$.
      \item Thus any $g \in Gal\left(L/K\right)$ induces an
        automorphism of $\mu_n \subset L$ and all such automorphisms
        are raising a root to a power that is prime to $n$.
        \footnote{
          This is because $\forall g \in Gal\left(L/K\right)$
          $g$ permutes roots of the irreducible polynomial
          $\Phi_n$. The roots a generated by means of $\zeta \to
          \zeta^{a_g}$, where $\left(a_g, n\right) = 1$. Therefore
          we can associate a root permutation (i.e. $g$) with the
          following map $\zeta \to
          \zeta^{a_g}$, where $\left(a_g, n\right) = 1$.
        }
      \item $Gal\left(L/K\right)  \hookrightarrow
        Aut\left(\mu_n\right) \cong
        \left(\mathbb{Z}/n\mathbb{Z}\right)^\times$. That
        \footnote{
          $Gal\left(L/K\right)  \hookrightarrow
          Aut\left(\mu_n\right)$
        }
        is because if a $g$ is an identity on $\mu_n$ then it is also
        identity on $L$ because $\mu_n$ generates $L$ over $K$
        \footnote{
          We have to proof there that $Gal\left(L/K\right)  \hookrightarrow
          Aut\left(\mu_n\right)$ is an \mynameref{def:embedding}
          i.e. \mynameref{def:injection} that preserves the group
          structure. The injection was proved before because for
          $g_1,g_2 \in Gal\left(L/K\right)$ such that $g_1 \ne g_2$ we
          have two different root exchange $\zeta \to \zeta^{a_{g_1}}$ and
          $\zeta \to \zeta^{a_{g_2}}$. About structure preserving if
          $f: g \to \left(\zeta \to \zeta_a\right)$ then easy check
          that $f\left(g_1 g_2\right) = f\left(g_1 \left) f\right(
          g_2\right)$ and that there is a homomorphism. By the way any
          embedding should preserve the identity element that was
          shown by Ekaterina.

          Comments from staff about the identity preserving: The proof
          of injectivity in the lecture goes as follows: take
          arbitrary element $g \in Gal(L/K)$. We prove, that if the
          image of $g$ is the identity in $(\mathbb{Z}/n)*$,
          then $g$ is itself the identity in $Gal(L/K)$.
          \label{note:lec6_staff_comment}
        }
       \item If $\Phi_n$ is irreducible then there is an isomorphism
         because of cardinality: $\left[L:K\right] = \deg \Phi_n =
         \phi\left(n\right)$. But
         $\phi\left(n\right) =
         \left|\left(\mathbb{Z}/n\mathbb{Z}\right)^\times\right|$. So in
         the case the embedding must be isomorphism.
    \end{enumerate}
  \end{proof}
  \label{thm:lec6_3}
\end{theorem}


text:
layout: page
title: Datenschutzerklärung
tags: [privacy]
comments: false
---

## Datenschutz

Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich.
Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder
eMail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis.
Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.

Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation
per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff
durch Dritte ist nicht möglich.

Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten
durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung
und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die
Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle
der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.

## Datenschutzerklärung für die Nutzung von Google Analytics

Diese Website benutzt Google Analytics, einen Webanalysedienst der Google Inc. ("Google").
Google Analytics verwendet sog. "Cookies", Textdateien, die auf Ihrem Computer gespeichert
werden und die eine Analyse der Benutzung der Website durch Sie ermöglichen. Die durch den
Cookie erzeugten Informationen über Ihre Benutzung dieser Website werden in der Regel an
einen Server von Google in den USA übertragen und dort gespeichert. Im Falle der Aktivierung
der IP-Anonymisierung auf dieser Webseite wird Ihre IP-Adresse von Google jedoch innerhalb
von Mitgliedstaaten der Europäischen Union oder in anderen Vertragsstaaten des Abkommens
über den Europäischen Wirtschaftsraum zuvor gekürzt.

Nur in Ausnahmefällen wird die volle IP-Adresse an einen Server von Google in
den USA übertragen und dort gekürzt. Im Auftrag des Betreibers dieser Website
wird Google diese Informationen benutzen, um Ihre Nutzung der Website
auszuwerten, um Reports über die Websiteaktivitäten zusammenzustellen und um
weitere mit der Websitenutzung und der Internetnutzung verbundene
Dienstleistungen gegenüber dem Websitebetreiber zu erbringen. Die im Rahmen
von Google Analytics von Ihrem Browser übermittelte IP-Adresse wird nicht mit
anderen Daten von Google zusammengeführt.

Sie können die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer
Browser-Software verhindern; wir weisen Sie jedoch darauf hin, dass Sie in diesem Fall
gegebenenfalls nicht sämtliche Funktionen dieser Website vollumfänglich werden nutzen
können. Sie können darüber hinaus die Erfassung der durch das Cookie erzeugten und auf
Ihre Nutzung der Website bezogenen Daten (inkl. Ihrer IP-Adresse) an Google sowie die
Verarbeitung dieser Daten durch Google verhindern, indem sie das unter dem folgenden Link
verfügbare Browser-Plugin herunterladen und installieren:
http://tools.google.com/dlpage/gaoptout?hl=de.

redpajama_set_name: RedPajamaGithub


text:
"""Tests that walk through Course Builder pages."""

__author__ = 'Mike Gainer (mgainer@google.com)'

import cgi
import re
import urllib

from common import crypto
from common import utils as common_utils
from controllers import sites
from controllers import utils
from models import courses
from models import model_caching
from models import models
from models import transforms
from modules.courses import settings
from modules.dashboard import filer
from modules.i18n_dashboard import i18n_dashboard
from tests.functional import actions
from tests.functional.actions import assert_contains

COURSE_NAME = 'admin_settings'
COURSE_TITLE = 'Admin Settings'
ADMIN_EMAIL = 'admin@foo.com'
NAMESPACE = 'ns_%s' % COURSE_NAME
BASE_URL = '/' + COURSE_NAME
ADMIN_SETTINGS_URL = '/%s%s' % (
    COURSE_NAME, settings.HtmlHookRESTHandler.URI)
TEXT_ASSET_URL = '/%s%s' % (
    COURSE_NAME, filer.TextAssetRESTHandler.URI)
STUDENT_EMAIL = 'student@foo.com'
SETTINGS_URL = '/%s/dashboard?action=settings_admin_prefs' % COURSE_NAME

class AdminSettingsTests(actions.TestBase):

    def setUp(self):
        super(AdminSettingsTests, self).setUp()
        actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE)
        actions.login(ADMIN_EMAIL)

    def test_defaults(self):
        prefs = models.StudentPreferencesDAO.load_or_default()
        self.assertEquals(False, prefs.show_hooks)

class WelcomePageTests(actions.TestBase):

    def setUp(self):
        super(WelcomePageTests, self).setUp()
        self.auto_deploy = sites.ApplicationContext.AUTO_DEPLOY_DEFAULT_COURSE
        sites.ApplicationContext.AUTO_DEPLOY_DEFAULT_COURSE = False

    def tearDown(self):
        sites.ApplicationContext.AUTO_DEPLOY_DEFAULT_COURSE = self.auto_deploy
        super(WelcomePageTests, self).tearDown()

    def test_welcome_page(self):
        actions.login(ADMIN_EMAIL, is_admin=True)
        response = self.get('/')
        self.assertEqual(response.status_int, 302)
        self.assertEqual(
            response.headers['location'],
            'http://localhost/admin/welcome')
        response = self.get('/admin/welcome?action=welcome')
        assert_contains('Welcome to Course Builder', response.body)
        assert_contains('action="/admin/welcome"', response.body)
        assert_contains('Start Using Course Builder', response.body)

    def test_welcome_page_button(self):
        actions.login(ADMIN_EMAIL, is_admin=True)
        response = self.post('/admin/welcome', {})
        self.assertEqual(response.status_int, 302)
        self.assertEqual(
            response.headers['location'],
            'http://localhost/modules/admin')

class HtmlHookTest(actions.TestBase):

    def setUp(self):
        super(HtmlHookTest, self).setUp()

        self.app_context = actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL,
                                            COURSE_TITLE)
        self.course = courses.Course(None, self.app_context)
        actions.login(ADMIN_EMAIL, is_admin=True)
        self.xsrf_token = crypto.XsrfTokenManager.create_xsrf_token(
            settings.HtmlHookRESTHandler.XSRF_ACTION)

    def tearDown(self):
        the_settings = self.course.get_environ(self.app_context)
        the_settings.pop('foo', None)
        the_settings['html_hooks'].pop('foo', None)
        self.course.save_settings(the_settings)
        super(HtmlHookTest, self).tearDown()

    def test_hook_edit_button_presence(self):

        # Turn preference on; expect to see hook editor button
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_hooks = True
            models.StudentPreferencesDAO.save(prefs)
        response = self.get(BASE_URL)
        self.assertIn('gcb-html-hook-edit', response.body)

        # Turn preference off; expect editor button not present.
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_hooks = False
            models.StudentPreferencesDAO.save(prefs)

        response = self.get(BASE_URL)
        self.assertNotIn('gcb-html-hook-edit', response.body)

    def test_non_admin_permissions_failures(self):
        actions.login(STUDENT_EMAIL)
        student_xsrf_token = crypto.XsrfTokenManager.create_xsrf_token(
            settings.HtmlHookRESTHandler.XSRF_ACTION)

        response = self.get(ADMIN_SETTINGS_URL)
        self.assertEquals(200, response.status_int)
        payload = transforms.loads(response.body)
        self.assertEquals(401, payload['status'])
        self.assertEquals('Access denied.', payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'key': 'base:after_body_tag_begins',
                'xsrf_token': cgi.escape(student_xsrf_token),
                'payload': '{}'})})
        payload = transforms.loads(response.body)
        self.assertEquals(401, payload['status'])
        self.assertEquals('Access denied.', payload['message'])

        response = self.delete(ADMIN_SETTINGS_URL + '?xsrf_token=' +
                               cgi.escape(student_xsrf_token))
        self.assertEquals(200, response.status_int)
        payload = transforms.loads(response.body)
        self.assertEquals(401, payload['status'])
        self.assertEquals('Access denied.', payload['message'])

    def test_malformed_requests(self):
        response = self.put(ADMIN_SETTINGS_URL, {})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Missing "request" parameter.', payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': 'asdfasdf'})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Malformed "request" parameter.', payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token)})})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Request missing "key" parameter.',
                          payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': 'base:after_body_tag_begins'})})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Request missing "payload" parameter.',
                          payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': 'base:after_body_tag_begins',
                'payload': 'asdfsdfasdf'})})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Malformed "payload" parameter.',
                          payload['message'])

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': 'base:after_body_tag_begins',
                'payload': '{}'})})
        payload = transforms.loads(response.body)
        self.assertEquals(400, payload['status'])
        self.assertEquals('Payload missing "hook_content" parameter.',
                          payload['message'])

    def test_get_unknown_hook_content(self):
        # Should be safe (but unhelpful) to ask for no hook.
        response = transforms.loads(self.get(ADMIN_SETTINGS_URL).body)
        payload = transforms.loads(response['payload'])
        self.assertIsNone(payload['hook_content'])

    def test_get_defaulted_hook_content(self):
        url = '%s?key=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape('base.after_body_tag_begins'))
        response = transforms.loads(self.get(url).body)
        self.assertEquals(200, response['status'])
        self.assertEquals('Success.', response['message'])
        payload = transforms.loads(response['payload'])
        self.assertEquals('',
                          payload['hook_content'])

    def test_page_has_defaulted_hook_content(self):
        response = self.get(BASE_URL)
        self.assertIn('', response.body)

    def test_set_hook_content(self):
        html_text = '

;<>

'

        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': 'base.after_body_tag_begins',
                'payload': transforms.dumps(
                    {'hook_content': html_text})})})
        self.assertEquals(200, response.status_int)
        response = transforms.loads(response.body)
        self.assertEquals(200, response['status'])
        self.assertEquals('Saved.', response['message'])

        # And verify that the changed text appears on course pages.
        # NOTE that text is as-is; no escaping of special HTML
        # characters should have been done.
        response = self.get(BASE_URL)
        self.assertIn(html_text, response.body)

    def test_delete_default_content_ineffective(self):
        response = self.get(BASE_URL)
        self.assertIn('', response.body)

        url = '%s?key=%s&xsrf_token=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape('base.after_body_tag_begins'),
            cgi.escape(self.xsrf_token))
        response = transforms.loads(self.delete(url).body)
        self.assertEquals(200, response['status'])
        self.assertEquals('Deleted.', response['message'])

        response = self.get(BASE_URL)
        self.assertIn('', response.body)

    def test_manipulate_non_default_item(self):
        html_text = '

;<>

'
        new_hook_name = 'html.some_new_hook'

        # Verify that content prior to setting is blank.
        url = '%s?key=%s&xsrf_token=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape(new_hook_name),
            cgi.escape(self.xsrf_token))
        response = transforms.loads(self.get(url).body)
        payload = transforms.loads(response['payload'])
        self.assertIsNone(payload['hook_content'])

        # Set the content.
        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': new_hook_name,
                'payload': transforms.dumps(
                    {'hook_content': html_text})})})
        self.assertEquals(200, response.status_int)
        response = transforms.loads(response.body)
        self.assertEquals(200, response['status'])
        self.assertEquals('Saved.', response['message'])

        # Verify that content after setting is as expected
        url = '%s?key=%s&xsrf_token=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape(new_hook_name),
            cgi.escape(self.xsrf_token))
        response = transforms.loads(self.get(url).body)
        payload = transforms.loads(response['payload'])
        self.assertEquals(html_text, payload['hook_content'])

        # Delete the content.
        response = transforms.loads(self.delete(url).body)
        self.assertEquals(200, response['status'])
        self.assertEquals('Deleted.', response['message'])

        # Verify that content after setting is None.
        url = '%s?key=%s&xsrf_token=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape(new_hook_name),
            cgi.escape(self.xsrf_token))
        response = transforms.loads(self.get(url).body)
        payload = transforms.loads(response['payload'])
        self.assertIsNone(payload['hook_content'])

    def test_add_new_hook_to_page(self):
        hook_name = 'html.my_new_hook'
        html_text = '

;<>

'
        key = 'views/base.html'
        url = '%s?key=%s' % (
            TEXT_ASSET_URL, cgi.escape(key))

        # Get base page template.
        response = transforms.loads(self.get(url).body)
        xsrf_token = response['xsrf_token']
        payload = transforms.loads(response['payload'])
        contents = payload['contents']

        # Add hook specification to page content.
        contents = contents.replace(
            '',
            '\n' +
            '{{ html_hooks.insert(\'%s\') | safe }}' % hook_name)
        self.put(TEXT_ASSET_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(xsrf_token),
                'key': key,
                'payload': transforms.dumps({'contents': contents})})})

        # Verify that new hook appears on page.
        response = self.get(BASE_URL)
        self.assertIn('id="%s"' % re.sub('[^a-zA-Z-]', '-', hook_name),
                      response.body)

        # Verify that modified hook content appears on page
        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': hook_name,
                'payload': transforms.dumps(
                    {'hook_content': html_text})})})

        response = self.get(BASE_URL)
        self.assertIn(html_text, response.body)

    def test_student_admin_hook_visibility(self):
        actions.login(STUDENT_EMAIL, is_admin=False)
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_hooks = True
            models.StudentPreferencesDAO.save(prefs)

        response = self.get(BASE_URL)
        self.assertNotIn('gcb-html-hook-edit', response.body)

        actions.login(ADMIN_EMAIL, is_admin=True)
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_hooks = True
            models.StudentPreferencesDAO.save(prefs)
        response = self.get(BASE_URL)
        self.assertIn('gcb-html-hook-edit', response.body)

    def test_hook_i18n(self):
        actions.update_course_config(
            COURSE_NAME,
            {
                'html_hooks': {'base': {'after_body_tag_begins': 'foozle'}},
                'extra_locales': [
                    {'locale': 'de', 'availability': 'available'},
                ]
            })

        hook_bundle = {
            'content': {
                'type': 'html',
                'source_value': '',
                'data': [{
                    'source_value': 'foozle',
                    'target_value': 'FUZEL',
                }],
            }
        }
        hook_key = i18n_dashboard.ResourceBundleKey(
            utils.ResourceHtmlHook.TYPE, 'base.after_body_tag_begins', 'de')
        with common_utils.Namespace(NAMESPACE):
            i18n_dashboard.ResourceBundleDAO.save(
                i18n_dashboard.ResourceBundleDTO(str(hook_key), hook_bundle))

        # Verify non-translated version.
        response = self.get(BASE_URL)
        dom = self.parse_html_string(response.body)
        html_hook = dom.find('.//div[@id="base-after-body-tag-begins"]')
        self.assertEquals('foozle', html_hook.text)

        # Set preference to translated language, and check that that's there.
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.locale = 'de'
            models.StudentPreferencesDAO.save(prefs)

        response = self.get(BASE_URL)
        dom = self.parse_html_string(response.body)
        html_hook = dom.find('.//div[@id="base-after-body-tag-begins"]')
        self.assertEquals('FUZEL', html_hook.text)

        # With no translation present, but preference set to foreign language,
        # verify that we fall back to the original language.

        # Remove translation bundle, and clear cache.
        with common_utils.Namespace(NAMESPACE):
            i18n_dashboard.ResourceBundleDAO.delete(
                i18n_dashboard.ResourceBundleDTO(str(hook_key), hook_bundle))
        model_caching.CacheFactory.get_cache_instance(
            i18n_dashboard.RESOURCE_BUNDLE_CACHE_NAME).clear()

        response = self.get(BASE_URL)
        dom = self.parse_html_string(response.body)
        html_hook = dom.find('.//div[@id="base-after-body-tag-begins"]')
        self.assertEquals('foozle', html_hook.text)

    def test_hook_content_found_in_old_location(self):
        actions.update_course_config(COURSE_NAME, {'foo': {'bar': 'baz'}})
        self.assertEquals(
            'baz', utils.HtmlHooks.get_content(self.course, 'foo.bar'))

    def test_insert_on_page_and_hook_content_found_using_old_separator(self):
        the_settings = self.course.get_environ(self.app_context)
        the_settings['html_hooks']['foo'] = {'bar': 'baz'}
        self.course.save_settings(the_settings)
        hooks = utils.HtmlHooks(self.course)
        content = hooks.insert('foo:bar')
        self.assertEquals('
baz
',
                          str(content))

    def test_hook_content_new_location_overrides_old_location(self):
        actions.update_course_config(COURSE_NAME,
                                     {'html_hooks': {'foo': {'bar': 'zab'}}})
        actions.update_course_config(COURSE_NAME,
                                     {'foo': {'bar': 'baz'}})
        self.assertEquals(
            'zab', utils.HtmlHooks.get_content(self.course, 'foo.bar'))

    def test_hook_rest_edit_removes_from_old_location(self):
        actions.update_course_config(COURSE_NAME,
                                     {'html_hooks': {'foo': {'bar': 'zab'}}})
        actions.update_course_config(COURSE_NAME,
                                     {'foo': {'bar': 'baz'}})
        response = self.put(ADMIN_SETTINGS_URL, {'request': transforms.dumps({
                'xsrf_token': cgi.escape(self.xsrf_token),
                'key': 'foo.bar',
                'payload': transforms.dumps({'hook_content': 'BAZ'})})})
        env = self.course.get_environ(self.app_context)
        self.assertNotIn('bar', env['foo'])
        self.assertEquals('BAZ', env['html_hooks']['foo']['bar'])

    def test_hook_rest_delete_removes_from_old_and_new_location(self):
        actions.update_course_config(COURSE_NAME,
                                     {'html_hooks': {'foo': {'bar': 'zab'}}})
        actions.update_course_config(COURSE_NAME,
                                     {'foo': {'bar': 'baz'}})
        url = '%s?key=%s&xsrf_token=%s' % (
            ADMIN_SETTINGS_URL, cgi.escape('foo.bar'),
            cgi.escape(self.xsrf_token))
        self.delete(url)

        env = self.course.get_environ(self.app_context)
        self.assertNotIn('bar', env['foo'])
        self.assertNotIn('bar', env['html_hooks']['foo'])

class JinjaContextTest(actions.TestBase):

    def setUp(self):
        super(JinjaContextTest, self).setUp()
        actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE)
        actions.login(ADMIN_EMAIL, is_admin=True)

    def _get_jinja_context_text(self, response):
        root = self.parse_html_string(response.text)
        div = root.find('body/div[last()-1]')
        return ''.join(div.itertext())

    def test_show_jinja_context_presence(self):

        # Turn preference on; expect to see context dump.
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_jinja_context = True
            models.StudentPreferencesDAO.save(prefs)
        self.assertIn('is_read_write_course:',
                      self._get_jinja_context_text(self.get(BASE_URL)))

        # Turn preference off; expect context dump not present.
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_jinja_context = False
            models.StudentPreferencesDAO.save(prefs)
        self.assertNotIn('is_read_write_course:',
                         self._get_jinja_context_text(self.get(BASE_URL)))

    def test_student_jinja_context_visibility(self):

        actions.login(STUDENT_EMAIL, is_admin=False)
        with common_utils.Namespace(NAMESPACE):
            prefs = models.StudentPreferencesDAO.load_or_default()
            prefs.show_jinja_context = True
            models.StudentPreferencesDAO.save(prefs)
        self.assertNotIn('is_read_write_course:',
                         self._get_jinja_context_text(self.get(BASE_URL)))

class ExitUrlTest(actions.TestBase):

    def setUp(self):
        super(ExitUrlTest, self).setUp()
        actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL, COURSE_TITLE)
        actions.login(ADMIN_EMAIL, is_admin=True)

    def test_exit_url(self):
        base_url = '/%s/dashboard?action=settings_data_pump' % COURSE_NAME
        url = base_url + '&' + urllib.urlencode({
            'exit_url': 'dashboard?%s' % urllib.urlencode({
                'action': 'data_pump'})})
        response = self.get(url)
        self.assertIn(
            'cb_global.exit_url = \'dashboard?action=data_pump',
            response.body)


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Classification;

namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.EmbeddedLanguages
{
    /// <inheritdoc cref="IEmbeddedLanguageClassifier"/>
    internal interface IAspNetCoreEmbeddedLanguageClassifier
    {
        /// <inheritdoc cref="IEmbeddedLanguageClassifier.RegisterClassifications"/>
        void RegisterClassifications(AspNetCoreEmbeddedLanguageClassificationContext context);
    }
}


text:
int do_assembly(const char*);
int do_run(const char*);
int do_tests();

int main(int argc, char** argv) {
	int ret = 0;

	switch (argc) {
	case 2:
		ret = string("test").compare(argv[1]) == 0 ? do_tests() : 1;
		break;
	case 3:
		if (string("assemble").compare(argv[1]) == 0) ret = do_assembly(argv[2]);
		else if (string("run").compare(argv[1]) == 0) ret = do_run(argv[2]);
		break;
	default:
		cout << "usage: " << argv[0] << " <6502 assembly file>" << endl;
		ret = 1;
	}

	return ret;
}

int do_assembly(const char* filename) {
	int ret = 0;
	auto assembler = Assembler(filename);

	cout << "build assembler for file " << filename << endl;

	try {
		while (!assembler.eof()) {
			stringstream lineout;
			lineout << assembler.current_line_number() << ":\t";

			vector<unsigned char> decoded = assembler.decodeline();
			for (auto c : decoded)
				lineout << "0x" << hex << (int)c;

			cout << lineout.str() << endl;
		}
	}
	catch (SyntaxException se) {
		cerr << "Failed to assemble file: " << se.what();
		ret = 1;
	}
	catch (UnknownInstruction ui) {
		cerr << "Failed to assemble file: " << ui.what();
		ret = 1;
	}
	catch (regex_error& re) {
		cerr << "A regular expression failed: " << re.what() << " " << re.code() << endl;
		ret = 1;
	}

	return ret;
}

int do_run(const char* filename) {
	int ret = 0;

	Executor e;

	if (e.load(filename)) e.run();

	return ret;
}


text:
using System;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace Example
{
	public partial class StartViewController : UIViewController
	{
		SignatureCaptureController _capture;
		public StartViewController (IntPtr handle) : base (handle)
		{
		}

		public override void ViewDidLoad ()
		{
			base.ViewDidLoad ();

			CapturedImage.Layer.BorderColor = UIColor.Black.CGColor;
			CapturedImage.Layer.BorderWidth = 2;
		}

		public override void DidRotate (MonoTouch.UIKit.UIInterfaceOrientation fromInterfaceOrientation)
		{
			base.DidRotate (fromInterfaceOrientation);

			if (IsInLandscapeOrentation()) {
				if (null == _capture) {
					_capture = UIStoryboard.FromName ("SignatureCapture", null).InstantiateViewController("SignatureCaptureController") as SignatureCaptureController;
					_capture.SignatureCaptured += this.SignatureCaptured;
				}
				this.PresentViewController (_capture, true, null);
			}
		}

		public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations ()
		{
			return UIInterfaceOrientationMask.Portrait | UIInterfaceOrientationMask.LandscapeLeft;
		}

		protected bool IsInLandscapeOrentation()
		{
			return this.InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft
				|| this.InterfaceOrientation == UIInterfaceOrientation.LandscapeRight;
		}

		protected void SignatureCaptured(object sender, SignatureCaptureEventArgs e)
		{
			if (e.HasSignature) {
				this.CapturedImage.Image = e.Signature;
			}
		}
	}
}


text:
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;

namespace SignalRest
{
    public class GroupManager : IGroupManager
    {
        public GroupManager(string hubName)
        {
            HubName = hubName;
        }

        private string HubName { get; }

        public async Task Add(string connectionId, string groupName)
        {
            ApiController.GroupAdd(HubName, connectionId, groupName);
            await GlobalHost.ConnectionManager.GetHubContext(HubName).Groups.Add(connectionId, groupName);
        }

        public async Task Remove(string connectionId, string groupName)
        {
            ApiController.GroupRemove(HubName, connectionId, groupName);
            await GlobalHost.ConnectionManager.GetHubContext(HubName).Groups.Remove(connectionId, groupName);
        }
    }
}


text:
CREATE TABLE authors (
  id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
  name VARCHAR(50) NOT NULL,
  birth_date TIMESTAMP NOT NULL,
  email VARCHAR(100),
  PRIMARY KEY(id)
);

CREATE TABLE articles (
  id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
  author_id BIGINT NOT NULL,
  title VARCHAR(100) NOT NULL,
  content CLOB(50k) NOT NULL,
  created_at TIMESTAMP NOT NULL,
  published_at TIMESTAMP,
  PRIMARY KEY (id)
);

ALTER TABLE articles ADD FOREIGN KEY (author_id) REFERENCES authors(id);

INSERT INTO authors (name, birth_date, email) VALUES ('Author1', '1970-01-01 12:00:00', 'author1@gmail.com');
INSERT INTO authors (name, birth_date, email) VALUES ('Author2', '1980-01-01 12:00:00', 'author2@gmail.com');

INSERT INTO articles (author_id, title, content, created_at)
  VALUES (1, 'First Artice', 'This is my first article', CURRENT_TIMESTAMP);
INSERT INTO articles (author_id, title, content, created_at)
  VALUES (1, 'Second Artice', 'This is my second article', CURRENT_TIMESTAMP);


text:
<!doctype html>

<meta charset="utf-8">
<title>The War of Independence for Enterprise Architecture – The New Dromologue</title>
<meta name="description" content="Velocity is all that matters.">
<meta name="keywords" content="Essay">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://www.dromologue.com/images/flora.jpg">

<meta name="twitter:title" content="The War of Independence for Enterprise Architecture">
<meta name="twitter:description" content="Velocity is all that matters.">
<meta name="twitter:creator" content="@dromologue">

<meta property="og:locale" content="en_US">
<meta property="og:type" content="article">
<meta property="og:title" content="The War of Independence for Enterprise Architecture">
<meta property="og:description" content="Velocity is all that matters.">
<meta property="og:url" content="http://www.dromologue.com/the-war-of-independence-for-enterprise/">
<meta property="og:site_name" content="The New Dromologue">

<link rel="canonical" href="http://www.dromologue.com/the-war-of-independence-for-enterprise/">
<link href="http://www.dromologue.com/feed.xml" type="application/atom+xml" rel="alternate" title="The New Dromologue Feed">

<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="http://www.dromologue.com/assets/css/main.css">

<link href="//fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic" rel="stylesheet" type="text/css">

<meta http-equiv="cleartype" content="on">

<link rel="shortcut icon" href="http://www.dromologue.com/favicon.ico">

<link rel="shortcut icon" href="http://www.dromologue.com/favicon.png">

<link rel="apple-touch-icon-precomposed" href="http://www.dromologue.com/images/apple-touch-icon-precomposed.png">

<link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://www.dromologue.com/images/apple-touch-icon-72x72-precomposed.png">

<link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://www.dromologue.com/images/apple-touch-icon-114x114-precomposed.png">

<link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://www.dromologue.com/images/apple-touch-icon-144x144-precomposed.png">

	<button class="dl-trigger">Open Menu</button>

Home

			About

Justin Arbuckle

CTO, IT Architect, Evangelist, Transformer.

Learn More

					 Email

					 Twitter

					 Facebook

					 LinkedIn

					 GitHub

			Posts

All Posts

All Tags

Link-List

Open Source Methods

RSS

Image source: Paul Klee

The War of Independence for Enterprise Architecture

<time datetime="2015-07-08T20:16:04+01:00">July 08, 2015</time>

What is Enterprise Architecture in a high velocity software business?

If Mark Andreessen is right, and I think that he is, that "Software is eating the world" then it is worth remembering that every business is a software business.

John Deere tractors are now mobile soil analysis labs, Volvo cars implement the equivalent of an ESB for all their internal electronics, and airlines compete based on the speed and efficiency of the airport gate scheduling systems. To quote another visionary, "The times, they are a-changing."

Give some thought to how your business is being transformed by how it, or its competitors, use technology to compete.

Let's restate our opening question to be,

"Where does the Enterprise Architecture profession need to go to add value to businesses whose very technology operating model is changing?"

If I recall those enterprise architects whom I know, few have fundamentally changed their operating model. Online, I still see recruiters advertising for Zachman and TOGAF experience, endure long discussions at conferences of mapping business strategy to IT components or initiatives and console friends in engineering bemoaning thick turgid documents describing roadmaps and standards.

How did we get here and was it ever a good idea?

In the days of yore, change was slow. Infrastructure was expensive and you didn't control your destiny. Purchasing decisions could and did take a long time, as did the delivery of the hardware. Software features from packaged applications were in thrall to customer councils in companies that were similarly slow to move and ship new features.

If today is an age of continuous delivery, back then it was fractal planning…everyone having to rely on another's roadmap that was only partly shared and understood. Custom software development in-house was infected by / shaped by these expectations.

If we could expect our vendors to provide us with long term costs and delivery dates why shouldn't we expect the same from our own developers? To be fair, this worked for a while. Who did banks compete with? Other banks. There was no comparison of feature delivery and agility between a bank and PopCap games. We didn't grow up expecting new features every week. An unconscious but arresting 'colusion of the similarly-paced' reigned in our expectations.

So, Planning change - it's direction and speed - was critical. While everybody was focused on their own application or system someone had to focus on what the whole corporate technology leviathan was lumbering towards. This is where the Enterprise Architects came in.

They made roadmaps showing how often we needed to renew software; how long it might take to replace a technology that was beginning to lag on skills support in the market; and how to effectively evaluate its replacement in core systems. All good and necessary things.

Of course, this set them apart from their colleagues who actually ran those systems, or used those languages etc. So began the great war of independence between architects and engineers. Any of us who have worked in large enterprises over the last 20 years have been involved in a few skirmishes between people classed as 'doers' and those classed as 'thinkers' (meaning - NOT doers.)

Conway's Law is, for me, the most important idea ever to come out of architecture. It states that organisations will tend to produce systems that mirror their communication structures. So the irony of the separation between the architects and the engineers should not be lost on us.

I am not attributing it as a single cause, but clearly this separation has contributed to a corporate perception of architecture as conceptual and contingent and engineering as practical and procedural. In an important way, we have constrained our architects ability to become equal participants in engineering projects, and our engineers from having meaningful input to technology strategy, because of this most pernicious idea.

Therefore, I infer a corollary to Conway's Law:

"The greater the functional segregation of an organisation, the greater the lag in effecting technology change."

Definitions of DevOps abound. It is clear though that what most of us mean when we talk about operating in 'this' way has something to do with;

releasing software in small batches, fast.

working in teams structured around required expertise and mutual respect and not organisational silos or complicated blame inducing SLA's.

getting everything out of the way that obstructs the delivery of customer value.

Automating the hell out of tasks that can be automated so that we can achieve 1 even faster.

We spend a great deal of time talking about the vertical impact of conway's law. DevOps has rightfully focused us on the collaboration between those that build software and those that run it. But we tend to spend much less time talking about how to evolve the role of the architect as we adopt these new agile practises and DevOps.

Enterprise Architects have a great deal of value to add to a DevOps aligned business. I think it comes down to four basic ideas:

Review

Renewal

Refactoring

Resilience

Review.

Unicorns, like Facebook or google, are relatively skills-flat. They have large teams of highly talented engineers and architects who work together to solve product problems. Horses, i.e. any organisation older than the public internet, tend to have a much lumpier skills profile where deep skills in one package or language is common and where multi-rolled / skilled technologists are more difficult to achieve.

An enterprise architect should act as a facilitator of discussion between the various technical stakeholders in an organisation, ensuring that technology decisions are made transparently and leveraging the best experience available across the enterprise, regardless of division or stripe.

This might take the form of an architecture review body. In my experience, those that exists solely for the purpose of approval and rubber stamping lead short and violent lives. All reviews, whether or not there is a decision gate in front of it, rest on the cogency of the discussion.

Now, some agilists may shake their heads in disapproval at the idea of a formal review structure. Frankly, in a perfect world, this wouldn't be necessary. But your typical large enterprise is on a journey of transformation that will likely take as many years to achieve critical mass as the age of its oldest code base.

So we can't assume anything. Much of the change we need to drive, whether as engineers or architects, needs to be prefaced with great gobs of education. Rather than coming from on high, open discussions between people working on important projects is the most effective way of seeing thew change in thinking occurring as well as to seed it.

Renewal.

Enterprises invest in a wide range of technologies. While polyglot programming is pervasive in many startups and web companies, it is far less common in the large enterprise. Everyone has their favourite language. Enterprise Architects again can facilitate a useful conversation on alternatives. Whereas in the past though, implementation was at an arm's length, today's successful EA's lead projects that produce an MVP using new technology. Without praxis in the use of the new technology and its implementation with existing enterprise assets, all credibility is lost.

Creating and testing scenarios for renewal of technology is a critical job. Doing this, together with, rather than TO, other technology, engineering managers also creates a deep shared understanding of the possible uses of the technology. In this instance both engineers and architects are contributing to an organisational understanding of both the conceptual / strategic implications of the technology as well as the practical / syntactic /workflow uses of the technology.

Refactoring.

All code bases evolve. Some slower than others. The newer web platforms and perhaps the core systems written in older object oriented technologies like Java lend themselves to refactoring within the development workflow. However, the transformation challenge in the large enterprise has much to do with the transformation of the older / legacy systems and the transformation of the 'practise' of implementing packaged applications (think ERP, HR systems, General Ledgers etc.) where your development practise has no control over the development practises of the vendor.

Traditionally if we want to deploy a large HR System implementation, we would spend a great deal of time collecting requirements, arguing with the vendor about how much those customisations would cost, waiting for the changes to be delivered and then hoping it all works as advertised on the infrastructure you ordered 18 months ago…

What is possible and preferable is instead deploying even this behemoth in small batches. For instance,

Iteration 1: deploy a small infrastructure footprint to support just the creation and modification of staff contact information.

Iteration 2: extend by integrating with current Active Directory infrastructure….

The EA in my experience needs to evangelise, promote, and drive this process of changing how we practise the evolution of technology in our business. An understanding of the architectures of packages chosen, or existing large systems is required to enable the design choices that underpin the design / factoring of the iterations. In this way, using approaches from Domain Driven Design or Martin Fowlers anecdotal 'Strangler Pattern', we can slowly evolve legacy systems. The factoring required for this is essential knowledge that can and should be investigated by EA's.

Resilience.

What kind of organisation do we want to create? A brief look through some business literature from Peters, Drucker, Rosenzweig, Collins etc. we can see that the only sure thing strategically speaking to predict company success is Resilience. Whatever that means. The EA needs to define what resilience both technically and culturally means for the technology organisation. So what exactly is resilience?

Karl Weck has done a great deal of work on the attributes of highly reliable organisations. These are organisations that literally cannot afford not to function. Good examples would be ER departments, Airline Pilots etc. He found some basic attributes of those organisations that were truly highly reliable:

Track small failures

Resist oversimplification

Sensitive to operations

Committed to resilience

Defer to expertise

Another blog post will go into these in more detail. The core idea here is that there is a conversation that EA's need to facilitate within a large organisation that gives them visibility of, commitment to and collaboration with how the organisation is structured and operated to achieve these goals.

Let's return to the original question. Enterprise Architects need to give up powerpoint.

Give up arbitrary standardization from a high tower. Start focusing on the 4 'R's. The future success of enterprise architecture as a profession will be based on how increasingly embedded in the operations of products and teams as they are formed.

Tweet me @dromologue.

        Essay

 Like

 Tweet

 +1

      Read More

Promotions

Junior staff often ask me, "what does it take to be promoted?" I am honest and don't pretend. I say, "It takes fitting in with how the or...… Continue reading

Scotiabank Wins Bank of the Year in Canada 2019

        Published on November 19, 2019

Google Next Keynote

        Published on May 02, 2019

    © 2021 Justin Arbuckle. Powered by Jekyll using the HPSTR Theme.

    Please enable JavaScript to view the comments powered by Disqus.
    comments powered by Disqus


text:
class AddOriginalIdToQuestionnaires < ActiveRecord::Migration
  def self.up
    add_column :questionnaires, :original_id, :integer
    add_foreign_key(:questionnaires, :questionnaires, {:column => :original_id, :dependent => :nullify})
  end

  def self.down
    remove_column :questionnaires, :original_id
  end
end


text:
/* This file was generated automatically by Zephir do not modify it! */

#ifndef ZEPHIR_CLASS_ENTRIES_H
#define ZEPHIR_CLASS_ENTRIES_H

#include "owl/cache/driver.zep.h"
#include "owl/filter/filterinterface.zep.h"
#include "owl/cache/driver/cachedriver.zep.h"
#include "owl/filter/abstractfilter.zep.h"
#include "owl/log/writerinterface.zep.h"
#include "owl/log/abstractwriter.zep.h"
#include "owl/log/loggerinterface.zep.h"
#include "owl/dbal/driver/abstractpdo.zep.h"
#include "owl/dbal/driver/driverinterface.zep.h"
#include "owl/dbal/platform/platforminterface.zep.h"
#include "owl/exception.zep.h"
#include "owl/http/responseinterface.zep.h"
#include "owl/log/formatterinterface.zep.h"
#include "owl/mvc/controllerinterface.zep.h"
#include "owl/router/route.zep.h"
#include "owl/applicationinterface.zep.h"
#include "owl/di/containerinterface.zep.h"
#include "owl/di/servicedefinitioninterface.zep.h"
#include "owl/dispatcherinterface.zep.h"
#include "owl/http/requestinterface.zep.h"
#include "owl/http/response.zep.h"
#include "owl/log/abstractlogger.zep.h"
#include "owl/mvc/controller.zep.h"
#include "owl/mvc/viewinterface.zep.h"
#include "owl/router/routerinterface.zep.h"
#include "owl/std/arraybag.zep.h"
#include "owl/std/collection/abstractcollection.zep.h"
#include "owl/annotations/annotation.zep.h"
#include "owl/annotations/classannotationsresult.zep.h"
#include "owl/annotations/exception.zep.h"
#include "owl/annotations/reader.zep.h"
#include "owl/application.zep.h"
#include "owl/bridge/lynx/rest/entitycontroller.zep.h"
#include "owl/cache/driver/memcache.zep.h"
#include "owl/cache/driver/memcached.zep.h"
#include "owl/cache/driver/nativearray.zep.h"
#include "owl/cache/driver/redis.zep.h"
#include "owl/console/application.zep.h"
#include "owl/console/commandinterface.zep.h"
#include "owl/dbal/connection.zep.h"
#include "owl/dbal/driver/mysql.zep.h"
#include "owl/dbal/driver/pdo.zep.h"
#include "owl/dbal/driver/pgsql.zep.h"
#include "owl/dbal/exception.zep.h"
#include "owl/dbal/platform/mysql.zep.h"
#include "owl/dbal/platform/pgsql.zep.h"
#include "owl/debug/memoryprofiler.zep.h"
#include "owl/debug/profiler.zep.h"
#include "owl/di/container.zep.h"
#include "owl/di/servicedefinition.zep.h"
#include "owl/event/event.zep.h"
#include "owl/event/manager.zep.h"
#include "owl/filter/email.zep.h"
#include "owl/filter/striptags.zep.h"
#include "owl/filter/trim.zep.h"
#include "owl/filter/url.zep.h"
#include "owl/http/headersbag.zep.h"
#include "owl/http/request.zep.h"
#include "owl/http/response/json.zep.h"
#include "owl/log/exception/invalidformatterexception.zep.h"
#include "owl/log/exception/invalidwriterexception.zep.h"
#include "owl/log/formatter/json.zep.h"
#include "owl/log/formatter/line.zep.h"
#include "owl/log/logger.zep.h"
#include "owl/log/record.zep.h"
#include "owl/log/writer/devnull.zep.h"
#include "owl/log/writer/echobrowser.zep.h"
#include "owl/log/writer/file.zep.h"
#include "owl/module/manager.zep.h"
#include "owl/mvc/view.zep.h"
#include "owl/mvc/view/engine/php.zep.h"
#include "owl/router/http/dynamicroute.zep.h"
#include "owl/router/http/staticroute.zep.h"
#include "owl/router/router.zep.h"
#include "owl/session/managerinterface.zep.h"
#include "owl/std/collection/arraycollection.zep.h"

#endif


text:
namespace Encog.ML
{
    /// <summary>
    /// Defines a Machine Learning Method that can be reset to an untrained
    /// starting point.  Most weight based machine learning methods, such
    /// as neural networks support this.  Support vector machines do not.
    /// </summary>
    ///
    public interface IMLResettable : IMLMethod
    {
        /// <summary>
        /// Reset the weights.
        /// </summary>
        ///
        void Reset();

        /// <summary>
        /// Reset the weights with a seed.
        /// </summary>
        ///
        /// <param name="seed">The seed value.</param>
        void Reset(int seed);
    }
}


text:
/*
 * Zed Attack Proxy (ZAP) and its related class files.
 *
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 * 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.
 */
package org.zaproxy.zap.extension.api;

import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.zaproxy.zap.utils.XMLStringUtil;

public class ApiException extends Exception {

	private static final long serialVersionUID = 1L;

	public enum Type {BAD_FORMAT, BAD_TYPE, NO_IMPLEMENTOR, BAD_ACTION, BAD_VIEW, BAD_OTHER, INTERNAL_ERROR, MISSING_PARAMETER,
		URL_NOT_FOUND, HREF_NOT_FOUND, SCAN_IN_PROGRESS, DISABLED, ALREADY_EXISTS, DOES_NOT_EXIST, ILLEGAL_PARAMETER, CONTEXT_NOT_FOUND,
		USER_NOT_FOUND, URL_NOT_IN_CONTEXT, BAD_API_KEY, SCRIPT_NOT_FOUND, BAD_SCRIPT_FORMAT, NO_ACCESS};

	private final String detail;

    private final Logger logger = Logger.getLogger(this.getClass());

	public ApiException(Type type) {
		super(type.name().toLowerCase());
		this.detail = null;
	}

    public ApiException(Type type, Throwable cause) {
        super(type.name().toLowerCase(), cause);
        this.detail = null;
    }

	public ApiException(Type type, String detail) {
		super(type.name().toLowerCase());
		this.detail = detail;
	}

    public ApiException(Type type, String detail, Throwable cause) {
        super(type.name().toLowerCase(), cause);
        this.detail = detail;
    }

	@Override
	public String toString () {
		return this.toString(true);
	}

	public String toString (boolean incDetails) {
		if (! incDetails) {
			return Constant.messages.getString("api.error." + super.getMessage());
		} else if (detail != null) {
			return Constant.messages.getString("api.error." + super.getMessage()) +
				" (" + super.getMessage() + ") : " + detail;
		} else {
			return Constant.messages.getString("api.error." + super.getMessage()) +
				" (" + super.getMessage() + ")";
		}
	}

	public String toString(API.Format format, boolean incDetails) {
		switch(format) {
		case HTML:
		case UI:
			return StringEscapeUtils.escapeHtml(this.toString(incDetails));

		case XML:
			try {
				DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
				DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

				Document doc = docBuilder.newDocument();
				Element rootElement = doc.createElement("Exception");
				doc.appendChild(rootElement);

				rootElement.setAttribute("type", "exception");
				rootElement.setAttribute("code", this.getMessage());
				if (incDetails && detail != null) {
					rootElement.setAttribute("detail", XMLStringUtil.escapeControlChrs(this.detail));
				}

				rootElement.appendChild(doc.createTextNode(XMLStringUtil.escapeControlChrs(this.toString(incDetails))));

				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);

				StringWriter sw = new StringWriter();
				StreamResult result =  new StreamResult(sw);
				transformer.transform(source, result);

				return sw.toString();

			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			break;

		case JSON:
			return this.toJSON(incDetails).toString();

		default:
			break;
		}
		return null;
	}

	private JSONObject toJSON (boolean incDetails) {
		JSONObject ja = new JSONObject();
		ja.put("code", super.getMessage());
		ja.put("message", Constant.messages.getString("api.error." + super.getMessage()));
		if (incDetails && detail != null) {
			ja.put("detail", detail);
		}
		return ja;
	}

}


text:
let template = require("./option.component.html");
let styles = require("./option.component.scss");

export const optionEvents = {
    CLICK: "[Option] Click"
};

export class OptionClick extends CustomEvent {
    constructor(option: { name: string, id: number }) {
        super(optionEvents.CLICK, { detail: { option } });
    }
}

export class OptionComponent extends HTMLElement {
    constructor() {
        super();
    }

    static get observedAttributes() {
        return ["option"];
    }

    connectedCallback() {
        this.textContent = this.option.name;
        this._addEventListeners();
    }

    private _addEventListeners() {
        this.addEventListener("click", this._onClick.bind(this));
    }

    private _onClick() {
        this.dispatchEvent(new OptionClick(this.option));
    }

    disconnectedCallback() {
        this.removeEventListener("click", this._onClick.bind(this));
    }

    public option: { name: string, id: number };

    attributeChangedCallback(name, oldValue, newValue) {
        switch (name) {
            case "option":
                this.option = JSON.parse(newValue);
                break;
        }
    }
}

customElements.define(`ce-option`, OptionComponent);


text:
/* @flow */
import { pipe } from 'klutils'

import { setCurrent, getNextTimerIndex } from './current'
import { stop } from './running'

import type { State, Timer } from 'types/timer'

import init from '../../../init'

import { showNotification } from 'utils/notifications'
import { getFormattedTime } from 'utils/timeFormat'
import { setPageTitle } from 'utils/document'
import makeReducer from 'utils/reducer'

export const MODIFY_TIMER = 'MODIFY_TIMER'
export const RESET_TIMER = 'RESET_TIMER'
export const START_TIMER = 'START_TIMER'
export const STOP_TIMER = 'STOP_TIMER'

export const findTimerByType = (state: State) => (timer: Timer) => timer.type === state.sequence[state.current]

const _timerFinished = (dispatch: Function, state: State) => {
  dispatch(stop())
  dispatch(resetTimer())

  const _setNextTimerBasedOnState = pipe(getNextTimerIndex, setCurrent, dispatch)
  _setNextTimerBasedOnState(state)

  showNotification('Potatoro', { body: 'Time\'s up!' })
}

const _tick = (tickLength: number) => (dispatch: Function, getState: Function) => {
  return window.setInterval(() => {
    const state = getState()

    if (state.running) {
      dispatch(modifyTimer())

      const currentTimer = state.timers.find(findTimerByType(state))

      if (currentTimer) {
        const durationInSeconds = currentTimer.duration * 60

        if ((state.elapsed >= durationInSeconds)) {
          _timerFinished(dispatch, state)
        } else {
          setPageTitle(getFormattedTime({ ...state, elapsed: state.elapsed + 1 }))
        }
      }
    }
  }, tickLength)
}

export function resetTimer (value: number = 0): Action {
  setPageTitle(undefined)

  return {
    type: RESET_TIMER,
    payload: value
  }
}

export function startTimer (tickLength: number = 1000): (dispatch: Function, getState: Function) => number {
  return _tick(tickLength)
}

export function modifyTimer (): Action {
  return {
    type: MODIFY_TIMER,
    payload: 1
  }
}

export function stopTimer (timerId: number): () => void {
  return () => window.clearInterval(timerId)
}

const modifyTimerHandler = (state: number, action: { payload: number }): number => state + action.payload
const resetTimerHandler = (state: number, action: { payload: number }): number => action.payload

export default makeReducer(init.elapsed, {
  [MODIFY_TIMER]: modifyTimerHandler,
  [RESET_TIMER]: resetTimerHandler
})


text:
package org.lnu.is.converter.operation.type;

import org.lnu.is.annotations.Converter;
import org.lnu.is.converter.AbstractConverter;
import org.lnu.is.domain.optype.OperationType;
import org.lnu.is.resource.operation.type.OperationTypeResource;

/**
 * Converter from operation type to operation type resource.
 *
 * @author kushnir
 *
 */
@Converter("operationTypeConverter")
public class OperationTypeConverter extends AbstractConverter<OperationType, OperationTypeResource> {

	@Override
	public OperationTypeResource convert(final OperationType source, final OperationTypeResource target) {
		target.setId(source.getId());
		target.setName(source.getName());
		target.setAbbrName(source.getAbbrName());

		return target;
	}

	@Override
	public OperationTypeResource convert(final OperationType source) {
		return convert(source, new OperationTypeResource());
	}

}


text:
title:  Lexíur Um Náð Og Miskunnsemi
date:  31/10/2020
---

### Lesefni vikunnar
1Mós 3.1-11; Róm 5. 11-19; 1Mós 28.10-17; Jóh 1.1-14; Matt 15.21-28; Mrk 10.46-52.

>
Minnistexti

> "Jesús sagði við hann: "Far þú, trú þín hefur bjargað þér." Jafnskjótt fékk hann sjónina og fylgdi honum á ferðinni" (Mrk 10.52).

Hvert okkar hefur aldrei blygðast sín? Hvert okkar hefur aldrei gert neitt sem við sjáum eftir og okkur hryllir við þeirri tilhugsun að einhver komist að því? Allar líkur benda til þess að við höfum öll orðið fyrir slíkri reynslu.

Ímyndaðu þér svo hvernig Adam og Evu var innanbrjósts eftir að þau átu af forboðna trénu. Eða þegar Jakob tældi föður sinn til að taka hann fram yfir eldri bróður hans og síðan varð hann að fara á flótta undan reiði bróðurins. Hvernig gat hann sofið á nóttunni? Og hugsaðu einnig um konuna sem var "staðin að verki þar sem hún var að drýgja hór" (Jóh 8.4). Davíð hafði einnig slíka reynslu og Slm 32 lætur í ljós biturleik hans og viðurkenningu á tilfinningum sínum.

Það er einmitt ein af ástæðunum fyrir því að fagnaðarerindið er altækt og dauði Krists var fyrir allt mannkyn. Þrátt fyrir að við séum frábrugðin hvert öðru þá er eitt sem sameinar okkur en það er almennur syndugleiki okkar.

Þar af leiðandi verður sönn kristin menntun að benda okkur á einustu lausnina á ömurlegu ástandi okkar. Þessa viku munum við líta á einustu lausn okkar: fyrirmynd okkar.


text:
require 'spec_helper'
require 'concerned_inheritance'

describe ConcernedInheritance::ClassMethods do

  let(:klass) do
    Class.new do
      extend ConcernedInheritance
    end
  end

  describe '.inherited' do

    context 'with a subclass' do
      it 'should call run inherited callbacks' do
        mock_subclass = mock
        klass.should_receive(:run_inherited_callbacks).with(mock_subclass)
        klass.send :inherited, mock_subclass
      end
    end

    context 'with a block' do
      it 'should call define_inherited_callback' do
        block = Proc.new { }
        klass.should_receive(:define_inherited_callback).with(&block)
        klass.send :inherited, &block
      end
    end

  end

  describe '.inherited_callbacks' do
    it 'should call off to its ancestors' do
      mock_ancestor = mock
      mock_callback      = proc { "Bar" }
      mock_ancestor.instance_variable_set :@inherited_callbacks, [mock_callback]
      klass.singleton_class.stub(:ancestors).and_return([mock_ancestor])
      klass.stub(:ancestors).and_return([mock_ancestor])
      klass.inherited_callbacks.size.should > 0
      klass.inherited_callbacks.each do |callback|
        callback.should == mock_callback
      end
    end
  end

  describe '.run_inherited_callbacks' do
    it 'should initialize an InheritanceDelegator' do
      mock_subclass = mock
      mock_callback = proc { }
      ConcernedInheritance::Delegator.should_receive(:new).with(klass, mock_subclass, mock_callback)
      klass.send :define_inherited_callback, &mock_callback
      klass.send :run_inherited_callbacks, mock_subclass
    end
  end

end