Current CheckIn
This commit is contained in:
parent
7bb3f5f080
commit
a73624b770
7 changed files with 117 additions and 66 deletions
|
@ -4,7 +4,7 @@
|
||||||
% If problems with the headers: get headings in appendix etc. right
|
% If problems with the headers: get headings in appendix etc. right
|
||||||
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
||||||
\chapter{Umfrage zur Optimierung}
|
\chapter{Umfrage zur Optimierung}
|
||||||
\label{ch:Umfrage}
|
\label{ap:opinion-poll}
|
||||||
|
|
||||||
Herzlich Willkommen
|
Herzlich Willkommen
|
||||||
|
|
||||||
|
|
|
@ -3,46 +3,9 @@
|
||||||
%*******************************************************
|
%*******************************************************
|
||||||
% If problems with the headers: get headings in appendix etc. right
|
% If problems with the headers: get headings in appendix etc. right
|
||||||
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
||||||
\chapter{Umfrage zur Optimierung}
|
\chapter{Zeitmessung der Webseite}
|
||||||
\label{ch:Umfrage}
|
\label{ap:timing}
|
||||||
|
|
||||||
Herzlich Willkommen
|
Mit dem nachfolgenden Skript werden die wichtigsten URL hinterlegt und jeweils mehrfach ausgeführt. Hierbei ist
|
||||||
|
|
||||||
\hfill
|
\includecode[Bash]{chapters/thesis/appendix02_timing.sh}{lst:timing}{Zeitmessung}
|
||||||
|
|
||||||
Diese Umfrage ist Teil der Bachelorarbeit >>Analyse und Optimierung der Webseite des Wedekind Projektes<< von Marco
|
|
||||||
Galster, die Rahmen des Projektes >>Edition der Korrespondenz Frank Wedekinds als Online"=Volltextdatenbank<< an der
|
|
||||||
Fernuni Hagen durchgeführt wird. In der Bachelorarbeit soll der aktuelle Prototyp auf Performance"=Probleme untersucht
|
|
||||||
und im Anschluss optimiert werden, um die Benutzerfreundlichkeit und die Akzeptanz der Anwendung zu verbessern.
|
|
||||||
Dies soll dazu führen, dass die digitalen Briefeditionen verstärkt bei der Forschung zur literarhistorischen und
|
|
||||||
kulturgeschichtlichen Wissenssteigerung eingesetzt werden.
|
|
||||||
|
|
||||||
\mytodos{der letzte Satz nochmal überarbeiten!}
|
|
||||||
|
|
||||||
% helfen das die FOrschung mithilfe solcher datenbank vorrangetrieben wird und somit die foschung an briefedition das Wissen über die Kultur erweitert
|
|
||||||
\hfill
|
|
||||||
|
|
||||||
Der aktuelle Prototyp der Anwendung wird unter \href{https://briefedition.wedekind.h-da.de} bereitgestellt. Die Fragen
|
|
||||||
sind bitte im Rahmen ihrer normalen Tätigkeit an dem Projekt zu beantworten. Bitte geben Sie so viele Informationen
|
|
||||||
mit an, die ihnen zu den Problemen mit auffallen.
|
|
||||||
|
|
||||||
\hfill
|
|
||||||
|
|
||||||
Wir bedanken uns im Voraus für ihre Zeit und die Teilnahme an der Umfrage. Für die Umfrage benötigen Sie ca. 10 Minuten.
|
|
||||||
|
|
||||||
\hfill
|
|
||||||
|
|
||||||
\begin{enumerate}
|
|
||||||
\item Welche Tätigkeit führen Sie aus? (Bearbeiter/Verwender)
|
|
||||||
|
|
||||||
\item Bitte geben Sie nun die Tätigkeiten an, bei denen immer wieder Verzögerung auftreten. Geben Sie bitte zu
|
|
||||||
jeder Tätigkeit noch folgende Informationen mit an:
|
|
||||||
|
|
||||||
\begin{itemize}
|
|
||||||
\item Wie häufig tritt die Verzögerung auf? (in Abhängigkeit zum Aufruf)
|
|
||||||
\item Gibt es einen zeitlichen Bezug? (z.B. tritt die Verzögerung nur Vormittags auf)
|
|
||||||
\item Tritt es immer einer bestimmten Abfolge auf, und wenn ja in welcher? (z.B. wenn man zuerst die
|
|
||||||
Benutzerliste anwählt und dann in den Bearbeiten-Modus wechselt)
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
59
chapters/thesis/appendix02_timing.sh
Normal file
59
chapters/thesis/appendix02_timing.sh
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
|
||||||
|
# Activate Bash Strict Mode
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
{
|
||||||
|
echo -e "URL\tRuns\tMin (ms)\tAvg (ms)\tMax (ms)"
|
||||||
|
for url in ${@:2}; do
|
||||||
|
get_statistics $url $1
|
||||||
|
done
|
||||||
|
} #| column -s $'\t' -t
|
||||||
|
}
|
||||||
|
|
||||||
|
get_statistics() {
|
||||||
|
# Initialice the variables
|
||||||
|
local min=1000000000
|
||||||
|
local max=0
|
||||||
|
local dur=0
|
||||||
|
|
||||||
|
# repeat for the defined counts the url calling
|
||||||
|
for i in $(seq 1 $2); do
|
||||||
|
local gp=$(($(get_posts $1)/1000000)) # from ns to ms
|
||||||
|
if [[ $gp -gt $max ]]
|
||||||
|
then max=$gp
|
||||||
|
fi
|
||||||
|
if [[ $gp -lt $min ]]
|
||||||
|
then min=$gp
|
||||||
|
fi
|
||||||
|
dur=$(( $dur + $gp ))
|
||||||
|
done
|
||||||
|
|
||||||
|
# output the statistic values
|
||||||
|
echo -e "$1\t$2\t$min\t$(($dur/$2))\t$max"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_posts() {
|
||||||
|
# Call the url with measure time
|
||||||
|
local start=$(date +%s%N)
|
||||||
|
curl --silent --show-error $1 > /dev/null
|
||||||
|
local stop=$(date +%s%N)
|
||||||
|
local dur=$(($stop-$start))
|
||||||
|
echo $dur
|
||||||
|
}
|
||||||
|
|
||||||
|
# the main domain
|
||||||
|
hostname="https://briefedition.wedekind.h-da.de"
|
||||||
|
|
||||||
|
# the Array of the Urls
|
||||||
|
url_arr=(
|
||||||
|
"$hostname/index.xhtml"
|
||||||
|
"$hostname/view/document/list.xhtml"
|
||||||
|
"$hostname/view/correspondent/list.xhtml"
|
||||||
|
"$hostname/view/person/list.xhtml"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Execute all the URLs for 10 rounds
|
||||||
|
main 10 ${url_arr[@]}
|
|
@ -24,7 +24,7 @@ Wartezeit auftritt. Zusätzlich soll noch dazu angegeben werden, wie häufig die
|
||||||
auftritt oder immer nur zu bestimmten Zeitpunkten. Des Weiteren wird die Information nachgefragt, ob die Probleme
|
auftritt oder immer nur zu bestimmten Zeitpunkten. Des Weiteren wird die Information nachgefragt, ob die Probleme
|
||||||
immer bei der gleichen Abfolge von Aktionen auftritt, oder die vorherigen Aktionen irrelevant sind.
|
immer bei der gleichen Abfolge von Aktionen auftritt, oder die vorherigen Aktionen irrelevant sind.
|
||||||
|
|
||||||
Die Anfrage wird im Anhang \ref{ch:Umfrage} dargestellt.
|
Die Umfrage wird im Anhang \ref{ap:opinion-poll} dargestellt.
|
||||||
|
|
||||||
\section{Allgemeine Betrachtung des Systems}
|
\section{Allgemeine Betrachtung des Systems}
|
||||||
\label{sec:concept:viewsystem}
|
\label{sec:concept:viewsystem}
|
||||||
|
@ -59,38 +59,63 @@ zwischengespeichert werden kann und daher diese Daten immer wieder direkt von de
|
||||||
\section{Untersuchung der Anwendung}
|
\section{Untersuchung der Anwendung}
|
||||||
\label{sec:concept:softwarestructure}
|
\label{sec:concept:softwarestructure}
|
||||||
|
|
||||||
Wie im Kapitel \ref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Zuerst wird der
|
Wie im Kapitel \ref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die
|
||||||
komplette Ablauf als BlackBox betrachtet, um neben der Umfrage, auch über automatisierte Anfragen, zu ermitteln wo die
|
PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher gehen wir nun weiter nach in den Schichten vom
|
||||||
größten Performance-Probleme auftreten.
|
Glassfish"=Server.
|
||||||
|
|
||||||
|
Die OpenJPA Cache Schicht wird nun einzeln untersucht. Hierfür werden die zuerst die Cache"=Statistik für Object"=Cache
|
||||||
|
und Query"=Cache aktiviert \citep[315]{MüllerWehr2012}. Die somit erfassten Werte, werden über eine Webseite
|
||||||
|
bereitgestellt, um die Daten Live vom Server verfolgen zu können. Zusätzlich können diese Daten über ein Skript
|
||||||
|
zyklisch abgefragt, gespeichert und vergleichen werden.
|
||||||
|
|
||||||
Hierbei ist jede
|
In der \ac{JPA} Schicht sind die Anzahl der Entitäten im Persistence Context zu beobachten. Die Anzahl der verschiedenen
|
||||||
Schicht einzeln, sowie der komplette Ablauf als BlackBox zu betrachten.
|
Klassen soll ermittelt und die Statistik"=Webseite um diese Daten erweitern. Um die Daten zu ermitteln, kann der
|
||||||
|
Quellcode aus \ref{lst:persistence-context-statistics} verwendet werden.
|
||||||
|
|
||||||
\mytodos{angenfangen bei jeder Schicht, kurz beschreiben und was da getan wird um dort etws zu untersuchen}
|
\begin{lstlisting}[language=Java,caption={Persistence"=Kontext Statistik},label=lst:persistence-context-statistics]
|
||||||
|
EntityManagerFactory emf = Persistence.createEntityManagerFactory(...);
|
||||||
|
EntityManager em = emf.createEntityManager();
|
||||||
|
for(EntityType<?> entityType : em.getMetaModel().getEntities())
|
||||||
|
{
|
||||||
|
Class<?> managedClass = entityType.getBindableJavaType();
|
||||||
|
System.out.println("Managing type: " + managedClass.getCanonicalName());
|
||||||
|
}
|
||||||
|
|
||||||
\mytodos{Zum enden dann den gesammten Server untersucht, durch automatisiert Test über shell-Skripte die jede Seite mehrfach
|
// Oder bei JPA 2.0
|
||||||
aufrufen und die Messung dazu protokolieren sowie die min und max werte (Skript als Listening in den Anhang?)}
|
emf.getCache().print();
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
% Anhand der Umfragen werden die verschiedenen Seiten ermittelt und mit den Tools überprüft
|
% \mytodos{\url{https://eclipse.dev/eclipselink/api/2.1/org/eclipse/persistence/jpa/JpaCache.html#getObject(java.lang.Class,%20java.lang.Object)}}
|
||||||
% Während dessen kann über ein Script die Seite automatisiert abgefragt und das Trace aktiv sind
|
|
||||||
% je nach Erkenntnis muss dann der Lösungsweg beschritten werden
|
Die Schicht \ac{EJB} besitzt keine Möglichkeit um eine sinnvolle Messung durchzuführen, daher wird hierfür keine
|
||||||
% Beachten des Speicherverbrauchs!
|
weiteren Messungen eingefügt.
|
||||||
|
|
||||||
|
Bei den \ac{JSP} wird eine Zeitmessung eingefügt. Hierfür müssen die Seiten so erweitert werden, dass zum einen die
|
||||||
|
Zeit gemessen wird um die Daten zu ermitteln. Zum anderen wird die Zeit gemessen wie lange es dann noch dauert um die
|
||||||
|
Seite mit den Daten zu rendern um diese an den Client auszuliefern. Diese 2 Zeiten sollen dann im Footer direkt auf der
|
||||||
|
Seite mit dargestellt werden. Somit kann der Benutzer auch direkt sehen, wenn das laden länger gedauert hat, an welcher
|
||||||
|
Stelle die Verzögerung aufgetreten ist.
|
||||||
|
|
||||||
|
Zum Schluss soll die gesamte Anwendung noch automatisiert getestet werden. Hierfür wird ein Shell-Skript erstellt, dass
|
||||||
|
automatisiert alle URLs der Webseite mehrfach abfragt. Die Dauer der Aufrufe der Webseiten werden gemessen und
|
||||||
|
statistisch ausgewertet. Für einen späteren Vergleich werden diese Informationen gesichert und mit einem erneuten Aufruf
|
||||||
|
nach den Optimierungen verglichen. Hierdurch kann auch festgestellt werden, ob die Optimierungen erfolgreich waren.
|
||||||
|
Das zugehörige Script ist im Anhang \ref{ap:timing} angehängt.
|
||||||
|
|
||||||
\section{Vergleich mit anderen Technologien}
|
\section{Vergleich mit anderen Technologien}
|
||||||
\label{sec:concept:technologiecompare}
|
\label{sec:concept:technologiecompare}
|
||||||
|
|
||||||
\mytodos{Noch tiefer eingehen}
|
\mytodos{Noch tiefer eingehen?}
|
||||||
|
|
||||||
Damit eine Umsetzung mit einer anderen Technologie umgesetzt werden kann, muss dies den kompletten Aufbau unterstützen,
|
Damit eine Umsetzung auf eine andere Technologie umgestellt werden kann, muss dies den kompletten Technologie"=Stack
|
||||||
wie dies die \ac{JSP} unterstützen. Daher fallen reine FrontEnd"=Bibliotheken wie VueJS oder React aus der Betrachtung
|
besitzen, wie dies von der \ac{JSP} unterstützt wird. Daher fallen reine FrontEnd"=Bibliotheken wie VueJS oder React aus
|
||||||
heraus, da sie zusätzlich noch einen Backend für die Anwendungslogik (englisch business logic) benötigt.
|
der Betrachtung heraus, da sie zusätzlich noch einen Backend für die Anwendungslogik (englisch business logic) benötigt.
|
||||||
|
|
||||||
\subsection{C\# - ASP.NET Core MVC}
|
\subsection{C\# - ASP.NET Core MVC}
|
||||||
\label{sec:concept:technologiecompare:aspnetcore}
|
\label{sec:concept:technologiecompare:aspnetcore}
|
||||||
|
|
||||||
Beim Vergleich zu \ac{JSP} steht ASP.NET Core MVC in nichts nach. Im großen und ganzen ist der Funktionsumfang der
|
Beim Vergleich zu \ac{JSP} steht ASP.NET Core MVC in nichts nach. Im großen und ganzen ist der Funktionsumfang der
|
||||||
gleiche und mit EntityFramework gibt es ebenfalls einen sehr mächtigen \ac{ORM}. Hierbei wird die Programmierung anhand
|
gleiche und mit dem EntityFramework gibt es ebenfalls einen sehr mächtigen \ac{ORM}. Hierbei wird die Programmierung anhand
|
||||||
des \ac{MVC}"=Entwurfsmuster implementiert \citep{AspNetCore:2024:MVC}. Dieses Muster erleichtert die Trennung der
|
des \ac{MVC}"=Entwurfsmuster implementiert \citep{AspNetCore:2024:MVC}. Dieses Muster erleichtert die Trennung der
|
||||||
Benutzeranforderungen, welche durch die Controller mithilfe der Modelle abgearbeitet werden, von der Bedienoberfläche,
|
Benutzeranforderungen, welche durch die Controller mithilfe der Modelle abgearbeitet werden, von der Bedienoberfläche,
|
||||||
die hier in der Standardelementen von Webseiten, wie \ac{HTML}, \ac{CSS} und Javascript definiert werden. Zusätzlich
|
die hier in der Standardelementen von Webseiten, wie \ac{HTML}, \ac{CSS} und Javascript definiert werden. Zusätzlich
|
||||||
|
@ -98,7 +123,7 @@ existiert noch ein spezifischer Syntax um die Daten dynamisch in die Seiten einz
|
||||||
|
|
||||||
Das System selbst ist in Schichten, auch Middleware genannt, aufgebaut \citep{AspNetCore:2024:Middleware}. Hierbei
|
Das System selbst ist in Schichten, auch Middleware genannt, aufgebaut \citep{AspNetCore:2024:Middleware}. Hierbei
|
||||||
übernimmt jede Middleware ihre entsprechende Aufgabe oder gibt die Anfrage an die nächste Middleware weiter und wartet
|
übernimmt jede Middleware ihre entsprechende Aufgabe oder gibt die Anfrage an die nächste Middleware weiter und wartet
|
||||||
auf deren Antwort um diese and den Client zurückzugeben.
|
auf deren Antwort um diese und den Client zurückzugeben.
|
||||||
Diese Konzept wird direkt vom Standard umgesetzt und somit sind die unterschiedlichen Verarbeitungen getrennt
|
Diese Konzept wird direkt vom Standard umgesetzt und somit sind die unterschiedlichen Verarbeitungen getrennt
|
||||||
implementiert worden, was zu besserer Wartbarkeit des Programmcodes führt. Und die eigene Anwendung kann dadurch
|
implementiert worden, was zu besserer Wartbarkeit des Programmcodes führt. Und die eigene Anwendung kann dadurch
|
||||||
je nach Bedarf die Middleware aktivierten, die wirklich benötigt wird.
|
je nach Bedarf die Middleware aktivierten, die wirklich benötigt wird.
|
||||||
|
@ -129,7 +154,7 @@ Go wird in eine native Anwendung übersetzt, da für die großen Betriebssystem
|
||||||
Anwendung in Go ebenfalls nahezu Plattformunabhängig. Durch den integrierten Cross-Compiler, kann die Software direkt
|
Anwendung in Go ebenfalls nahezu Plattformunabhängig. Durch den integrierten Cross-Compiler, kann die Software direkt
|
||||||
für andere Betriebssystem mit erstellte werden.
|
für andere Betriebssystem mit erstellte werden.
|
||||||
|
|
||||||
Für eine dynamische Webseite, reichen die Standard-Bibliotheken, wobei auch gibt es verschiedene Frameworks die
|
Für eine dynamische Webseite, reichen die Standard-Bibliotheken, wobei auch hier gibt es verschiedene Frameworks die
|
||||||
eine Unterstützung für \ac{MVC} einbauen. Ein direkter \ac{ORM} ist ebenfalls vorhanden, um den einfachen Zugriff
|
eine Unterstützung für \ac{MVC} einbauen. Ein direkter \ac{ORM} ist ebenfalls vorhanden, um den einfachen Zugriff
|
||||||
auf eine Datenbank zu ermöglichen.
|
auf eine Datenbank zu ermöglichen.
|
||||||
|
|
||||||
|
@ -159,8 +184,6 @@ bekannt und Entwickelt wurde. Zudem ist die Programmiersprache sehr jung und hat
|
||||||
größte Nachteil darin ist aber, dass hierfür noch nicht so viele Entwickler existieren, die dann das Projekt
|
größte Nachteil darin ist aber, dass hierfür noch nicht so viele Entwickler existieren, die dann das Projekt
|
||||||
unterstützen können.
|
unterstützen können.
|
||||||
|
|
||||||
Mein Einschätzung nach, wäre ein Umstieg im aktuellen Stadium nicht sehr sinnvoll, da zum einen der großteil der
|
Meiner Einschätzung nach, wäre ein Umstieg im aktuellen Stadium nicht sehr sinnvoll, da zum einen der großteil der
|
||||||
Anforderung umgesetzt ist, und für jeden Änderung die Mitarbeiter sich erst in die neue Code-Basis einarbeiten müssten.
|
Anforderung umgesetzt ist, und für jeden Änderung die Mitarbeiter sich erst in die neue Code-Basis einarbeiten müssten.
|
||||||
Bei Weiterentwicklungen durch Studenten, ist man mit Java im Vorteil, da dies an der Uni gelehrt wird.
|
Bei Weiterentwicklungen durch Studenten, ist man mit Java im Vorteil, da dies an der Uni gelehrt wird.
|
||||||
|
|
||||||
\mytodos{Noch entscheiden, ob der Compare direkt bei der Technologie gemacht \\ wird, oder allgemein am ende}
|
|
||||||
|
|
|
@ -59,3 +59,4 @@
|
||||||
\definecolor{RoyalBlue}{cmyk}{1, 0.50, 0, 0}
|
\definecolor{RoyalBlue}{cmyk}{1, 0.50, 0, 0}
|
||||||
% \definecolor{Black}{cmyk}{0, 0, 0, 0}
|
% \definecolor{Black}{cmyk}{0, 0, 0, 0}
|
||||||
\definecolor{Black}{HTML}{221E1F} % Definition von https://en.wikibooks.org/wiki/LaTeX/Colors
|
\definecolor{Black}{HTML}{221E1F} % Definition von https://en.wikibooks.org/wiki/LaTeX/Colors
|
||||||
|
\definecolor{Green}{HTML}{00A64f}
|
||||||
|
|
BIN
thesis.pdf
BIN
thesis.pdf
Binary file not shown.
|
@ -19,8 +19,10 @@
|
||||||
|
|
||||||
% https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings
|
% https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings
|
||||||
%\lstinputlisting[frame=tb,language=SQL,caption={ein sql beispiel},label=lst:tester]{chapters/thesis/chapter05_example.sql}
|
%\lstinputlisting[frame=tb,language=SQL,caption={ein sql beispiel},label=lst:tester]{chapters/thesis/chapter05_example.sql}
|
||||||
\newcommand{\includecode}[4][c]{\lstinputlisting[caption=#4,frame=tb,label=#3,language=#1]{#2}}
|
\newcommand{\includecode}[4][c]{\lstinputlisting[caption=#4,label=#3,language=#1]{#2}}
|
||||||
|
\lstset{frame=tb}
|
||||||
\newcommand\mytodos[1]{\fcolorbox{black}{lightgray}{\textit{\textcolor{red}{TODO: #1}}}}
|
\newcommand\mytodos[1]{\fcolorbox{black}{lightgray}{\textit{\textcolor{red}{TODO: #1}}}}
|
||||||
|
|
||||||
% Beispiel für externe Datei:
|
% Beispiel für externe Datei:
|
||||||
%\includecode[SQL]{chapters/thesis/chapter05_example.sql}{lst:tester}{ein sql beispiel}
|
%\includecode[SQL]{chapters/thesis/chapter05_example.sql}{lst:tester}{ein sql beispiel}
|
||||||
% Beispiel für direkte Eingabe:
|
% Beispiel für direkte Eingabe:
|
||||||
|
@ -30,6 +32,8 @@
|
||||||
% { do nothing or other things }
|
% { do nothing or other things }
|
||||||
% end;
|
% end;
|
||||||
%\end{lstlisting}
|
%\end{lstlisting}
|
||||||
|
% Beispiel für Inline:
|
||||||
|
%lorem ipsum \lstinline|code| lorem ipsum
|
||||||
|
|
||||||
|
|
||||||
%*************************************************************************
|
%*************************************************************************
|
||||||
|
@ -91,6 +95,7 @@
|
||||||
\cleardoublepage
|
\cleardoublepage
|
||||||
\part{Appendix}
|
\part{Appendix}
|
||||||
\include{chapters/thesis/appendix01}
|
\include{chapters/thesis/appendix01}
|
||||||
|
\include{chapters/thesis/appendix02}
|
||||||
%\include{chapters/examples/appendix02}
|
%\include{chapters/examples/appendix02}
|
||||||
%*************************************************************************
|
%*************************************************************************
|
||||||
% Other Stuff in the Back
|
% Other Stuff in the Back
|
||||||
|
|
Loading…
Reference in a new issue