Skip to content
Snippets Groups Projects
Commit 1508dd5f authored by Brutzman, Don's avatar Brutzman, Don
Browse files

updated plaintext file-recording default, intersperse PDU type and date/time of receipt

parent f1bb52bf
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,8 @@ import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
......@@ -42,14 +44,14 @@ public class PduPlayer {
private int port;
private Thread playerThread;
static final String ENCODING_BASE64 = "ENCODING_BASE64";
static final String ENCODING_PLAINTEXT = "ENCODING_PLAINTEXT";
static final String ENCODING_BINARY = "ENCODING_BINARY"; // TODO likely requires different code path
static final String ENCODING_XML = "ENCODING_XML"; // TODO, repeat Open-DIS version 4 effort
static final String ENCODING_EXI = "ENCODING_EXI"; // TODO, use Exificient or Nagasena libraries
static final String ENCODING_JSON = "ENCODING_JSON"; // TODO, repeat Open-DIS version 4 effort
static final String ENCODING_CDIS = "ENCODING_CDIS"; // future work based on new SISO standard
static final String ENCODING_MAK_DATA_LOGGER = "ENCODING_MAK_DATA_LOGGER"; // verbose pretty-print. perhaps output only (MAK format itself is binary)
static final String ENCODING_BASE64 = "ENCODING_BASE64";
static final String ENCODING_PLAINTEXT = "ENCODING_PLAINTEXT";
static final String ENCODING_BINARY = "ENCODING_BINARY"; // TODO likely requires different code path
static final String ENCODING_XML = "ENCODING_XML"; // TODO, repeat Open-DIS version 4 effort
static final String ENCODING_EXI = "ENCODING_EXI"; // TODO, use Exificient or Nagasena libraries
static final String ENCODING_JSON = "ENCODING_JSON"; // TODO, repeat Open-DIS version 4 effort
static final String ENCODING_CDIS = "ENCODING_CDIS"; // future work based on new SISO standard
static final String ENCODING_MAK_DATA_LOGGER = "ENCODING_MAK_DATA_LOGGER"; // verbose pretty-print. perhaps output only (MAK format itself is binary)
static final String ENCODING_WIRESHARK_DATA_LOGGER = "ENCODING_WIRESHARK_DATA_LOGGER"; //
private static String pduLogEncoding = PduRecorder.ENCODING_PLAINTEXT; // determined when reading file
......@@ -161,9 +163,11 @@ public class PduPlayer {
pduLogEncoding = PduRecorder.ENCODING_PLAINTEXT;
else pduLogEncoding = PduRecorder.ENCODING_BINARY;
sleep (100l); // let prior run finish
System.out.flush();
System.err.flush();
System.out.println("Replaying PDU log file with " + pduLogEncoding + ": " + f.getAbsolutePath());
System.out.flush();
for (String line : lines)
{
......@@ -171,8 +175,11 @@ public class PduPlayer {
sleep(100l); // TODO confirm usability OK, currently 100 msec increments for pause
}
if (line.length() <= 0)
; // blank lines ok
else if (line.trim().startsWith(PduRecorder.COMMENT_MARKER)) {
{
// blank lines ok
}
else if (line.trim().startsWith(PduRecorder.COMMENT_MARKER))
{
if (handleComment(line, f)) {
break;
}
......@@ -193,9 +200,25 @@ public class PduPlayer {
}
if (line.contains("[") || line.contains("]"))
{
System.out.println("*** [square brackets] no longer included in CSV PLAINTEXT data, ignored");
System.out.println("*** [square brackets] no longer included in CSV PLAINTEXT encoded data, [] characters ignored");
line = line.replace("[","").replace("]","");
}
String dateString = new String();
String timeString = new String();
LocalDate localDate;
LocalTime localTime;
if (line.startsWith("DisPduType"))
{
// strip prepended DisPduTye, receipt date, receipt time
line = line.substring(line.indexOf(",") + 1); // strip DisPduTye
dateString = line.substring(0,line.indexOf(","));
localDate = LocalDate.parse(dateString);
line = line.substring(line.indexOf(",") + 1); // strip receipt date
timeString = line.substring(0,line.indexOf(","));
localTime = LocalTime.parse(timeString);
line = line.substring(line.indexOf(",") + 1); // strip receipt time
}
//Pattern splitting needed for playback of unencoded streams
// REGEX = "\\],\\[";
REGEX = ",";
......@@ -207,11 +230,10 @@ public class PduPlayer {
// //Add the "]" to the end of sa[0]. It was taken off by the split
// if (sa.length > 1)
// sa[1] = "[".concat(sa[1]);
break;
default:
System.err.println("Encoding'" + pduLogEncoding + " not recognized or supported");
System.err.println("Encoding'" + pduLogEncoding + "' not recognized or supported");
}
// timestamp is 8 bytes, size of smallest PDU?
......@@ -223,7 +245,7 @@ public class PduPlayer {
exitWithFailure();
}
if (startNanoTime == null) {
if (startNanoTime == null) { // TODO check if reset during multiple encoding passes
startNanoTime = System.nanoTime(); // initialize
}
// get timestamp pduTimeBytes, i.e. 8 bytes represented by a Java long
......@@ -283,7 +305,8 @@ public class PduPlayer {
now = System.nanoTime();
sleepTime = targetSimTime - now; // the difference between then and now
if (sleepTime > 20000000) { // 20 msec
if (sleepTime > 20000000)// 20 msec
{
//System.out.println("sim interval = " + pduTimeInterval + ", sleeping for " + sleepTime/1000000l + " ms");
sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
}
......@@ -502,14 +525,23 @@ public class PduPlayer {
closeConnections();
}
private void sleep(long ms) {
sleep(ms, 0);
private void sleep(long ms)
{
if (ms > 10000)
{
System.err.println ("*** PduPlayer sleep > 10 seconds, ignored (ms=" + ms + ")");
}
else sleep(ms, 0);
}
private void sleep(long ms, int ns) {
// @formatter:off
try {
Thread.sleep(ms, ns);
if (ms > 10000)
{
System.err.println ("*** PduPlayer sleep > 10 seconds, ignored (ms=" + ms + ")");
}
else Thread.sleep(ms, ns);
} catch (InterruptedException ex) {}
// @formatter:on
}
......
ant -f C:\\x3d-github\\open-dis7-java -Dnb.internal.action.name=run.single -Djavac.includes=edu/nps/moves/dis7/utilities/stream/PduPlayer.java -Drun.class=edu.nps.moves.dis7.utilities.stream.PduPlayer run-single
ant -f C:\\x3d-github\\opendis7-java -Dnb.internal.action.name=run.single -Djavac.includes=edu/nps/moves/dis7/utilities/stream/PduPlayer.java -Drun.class=edu.nps.moves.dis7.utilities.stream.PduPlayer run-single
init:
Deleting: C:\x3d-github\open-dis7-java\build\built-jar.properties
Deleting: C:\x3d-github\opendis7-java\build\built-jar.properties
deps-jar:
Updating property file: C:\x3d-github\open-dis7-java\build\built-jar.properties
Compiling 1 source file to C:\x3d-github\open-dis7-java\build\classes
Updating property file: C:\x3d-github\opendis7-java\build\built-jar.properties
Compiling 1 source file to C:\x3d-github\opendis7-java\build\classes
warning: [options] bootstrap class path not set in conjunction with -source 8
1 warning
compile-single:
run-single:
Prepare for PduPlayer self-test log by running PduRecorder() self-test first.
PduPlayer begin() playing DIS logs found in ancestor pduLog directory.
Replaying PDU log file with ENCODING_BASE64: C:\x3d-github\opendis7-java\pduLog\PduRecorderSelfTestENCODING_BASE64_PduCaptureLog.dislog
Sent PDU: DisPduType 01 ENTITY_STATE
Sent PDU: DisPduType 02 FIRE
Sent PDU: DisPduType 03 DETONATION
Sent PDU: DisPduType 04 COLLISION
Sent PDU: DisPduType 05 SERVICE_REQUEST
Sent PDU: DisPduType 06 RESUPPLY_OFFER
Sent PDU: DisPduType 07 RESUPPLY_RECEIVED
Sent PDU: DisPduType 08 RESUPPLY_CANCEL
Sent PDU: DisPduType 09 REPAIR_COMPLETE
Sent PDU: DisPduType 10 REPAIR_RESPONSE
Sent PDU: DisPduType 11 CREATE_ENTITY
Sent PDU: DisPduType 12 REMOVE_ENTITY
Sent PDU: DisPduType 13 START_RESUME
Sent PDU: DisPduType 14 STOP_FREEZE
Sent PDU: DisPduType 15 ACKNOWLEDGE
Sent PDU: DisPduType 16 ACTION_REQUEST
Sent PDU: DisPduType 17 ACTION_RESPONSE
Sent PDU: DisPduType 18 DATA_QUERY
Sent PDU: DisPduType 19 SET_DATA
Sent PDU: DisPduType 20 DATA
Sent PDU: DisPduType 21 EVENT_REPORT
Sent PDU: DisPduType 22 COMMENT
Sent PDU: DisPduType 23 ELECTROMAGNETIC_EMISSION
Sent PDU: DisPduType 24 DESIGNATOR
Sent PDU: DisPduType 25 TRANSMITTER
Sent PDU: DisPduType 26 SIGNAL
Sent PDU: DisPduType 27 RECEIVER
Sent PDU: DisPduType 28 IDENTIFICATION_FRIEND_OR_FOE
Sent PDU: DisPduType 29 UNDERWATER_ACOUSTIC
Sent PDU: DisPduType 30 SUPPLEMENTAL_EMISSION_ENTITY_STATE
Sent PDU: DisPduType 31 INTERCOM_SIGNAL
Sent PDU: DisPduType 32 INTERCOM_CONTROL
Sent PDU: DisPduType 33 AGGREGATE_STATE
Sent PDU: DisPduType 34 ISGROUPOF
Sent PDU: DisPduType 35 TRANSFER_OWNERSHIP
Sent PDU: DisPduType 36 ISPARTOF
Sent PDU: DisPduType 37 MINEFIELD_STATE
Sent PDU: DisPduType 38 MINEFIELD_QUERY
Sent PDU: DisPduType 39 MINEFIELD_DATA
Sent PDU: DisPduType 40 MINEFIELD_RESPONSE_NACK
Sent PDU: DisPduType 41 ENVIRONMENTAL_PROCESS
Sent PDU: DisPduType 42 GRIDDED_DATA
Sent PDU: DisPduType 43 POINT_OBJECT_STATE
Sent PDU: DisPduType 44 LINEAR_OBJECT_STATE
Sent PDU: DisPduType 45 AREAL_OBJECT_STATE
Sent PDU: DisPduType 46 TIME_SPACE_POSITION_INFORMATION
Sent PDU: DisPduType 47 APPEARANCE
Sent PDU: DisPduType 48 ARTICULATED_PARTS
Sent PDU: DisPduType 49 LIVE_ENTITY_FIRE
Sent PDU: DisPduType 50 LIVE_ENTITY_DETONATION
Sent PDU: DisPduType 51 CREATE_ENTITY_RELIABLE
Sent PDU: DisPduType 52 REMOVE_ENTITY_RELIABLE
Sent PDU: DisPduType 53 START_RESUME_RELIABLE
Sent PDU: DisPduType 54 STOP_FREEZE_RELIABLE
Sent PDU: DisPduType 55 ACKNOWLEDGE_RELIABLE
Sent PDU: DisPduType 56 ACTION_REQUEST_RELIABLE
Sent PDU: DisPduType 57 ACTION_RESPONSE_RELIABLE
Sent PDU: DisPduType 58 DATA_QUERY_RELIABLE
Sent PDU: DisPduType 59 SET_DATA_RELIABLE
Sent PDU: DisPduType 60 DATA_RELIABLE
Sent PDU: DisPduType 61 EVENT_REPORT_RELIABLE
Sent PDU: DisPduType 62 COMMENT_RELIABLE
Sent PDU: DisPduType 63 RECORD_RELIABLE
Sent PDU: DisPduType 64 SET_RECORD_RELIABLE
Sent PDU: DisPduType 65 RECORD_QUERY_RELIABLE
Sent PDU: DisPduType 66 COLLISION_ELASTIC
Sent PDU: DisPduType 67 ENTITY_STATE_UPDATE
Sent PDU: DisPduType 68 DIRECTED_ENERGY_FIRE
Sent PDU: DisPduType 69 ENTITY_DAMAGE_STATUS
Sent PDU: DisPduType 70 INFORMATION_OPERATIONS_ACTION
Sent PDU: DisPduType 71 INFORMATION_OPERATIONS_REPORT
Sent PDU: DisPduType 72 ATTRIBUTE
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Replaying PDU log file with ENCODING_BINARY: C:\x3d-github\opendis7-java\pduLog\PduRecorderSelfTestENCODING_BINARY_PduCaptureLog.dislog
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
Encoding'ENCODING_BINARY' not recognized or supported
ENCODING_PLAINTEXT
Replaying PDU log file with ENCODING_PLAINTEXT: C:\x3d-github\open-dis7-java\pduLog\PduRecorderSelfTestENCODING_PLAINTEXT_PduCaptureLog.dislog
Replaying PDU log file with ENCODING_PLAINTEXT: C:\x3d-github\opendis7-java\pduLog\PduRecorderSelfTestENCODING_PLAINTEXT_PduCaptureLog.dislog
Sent PDU: DisPduType 01 ENTITY_STATE
Sent PDU: DisPduType 02 FIRE
Sent PDU: DisPduType 03 DETONATION
......@@ -82,6 +178,6 @@ Sent PDU: DisPduType 69 ENTITY_DAMAGE_STATUS
Sent PDU: DisPduType 70 INFORMATION_OPERATIONS_ACTION
Sent PDU: DisPduType 71 INFORMATION_OPERATIONS_REPORT
Sent PDU: DisPduType 72 ATTRIBUTE
Total PDUs: 72
Total PDUs: 164
PduPlayer handleComment() found FINISH_COMMENT_MARKER, end of replay from log file PduRecorderSelfTestENCODING_PLAINTEXT_PduCaptureLog.dislog
BUILD SUCCESSFUL (total time: 8 seconds)
......@@ -110,14 +110,47 @@ public class PduRecorder // implements PduReceiver
private DisThreadedNetworkInterface disThreadedNetworkInterface;
private DisThreadedNetworkInterface.RawPduListener disRawPduListener;
private long startNanoTime = -1; // sentinel
private StringBuilder sb = new StringBuilder();
private Base64.Encoder base64Encoder = Base64.getEncoder();
private int pduCount = 0; // debug
private boolean headerWritten = false;
private boolean running = true; // starts recording by default
private boolean readableTimeStamp = true; // use normal date, time strings vice bytes
private long sessionDuration = -1;
private long startNanoTime = -1; // sentinel
private StringBuilder sb = new StringBuilder();
private Base64.Encoder base64Encoder = Base64.getEncoder();
private int pduCount = 0; // debug
private boolean headerWritten = false;
private boolean running = true; // starts recording by default
private boolean readableTimeStamp = true; //
private boolean zeroBasedTimeStamp = true; // use normal date, time strings vice bytes
private long sessionDuration = -1;
public static final String UNDATED = "undated";
public enum TimeFormatterType
{
SECONDS,
TENTHSECONDS,
HUNDREDTHSECONDS,
MILLISECONDS,
MICROSECONDS,
NANOSECONDS;
}
/** Format time <code>HH:mm:ss</code>
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterSeconds = DateTimeFormatter.ofPattern("HH:mm:ss");
/** Format time <code>HH:mm:ss.S</code>, default
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterTenthSeconds = DateTimeFormatter.ofPattern("HH:mm:ss.S");
/** Format time <code>HH:mm:ss.SS</code>
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterHundredthSeconds = DateTimeFormatter.ofPattern("HH:mm:ss.SS");
/** Format time <code>HH:mm:ss.SSS</code>
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterMilliSeconds = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
/** Format time <code>HH:mm:ss.SSSSSS</code>
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterMicroSeconds = DateTimeFormatter.ofPattern("HH:mm:ss.SSSSSS");
/** Format time <code>HH:mm:ss.SSSSSSSSS</code>
* @see java.time.format.DateTimeFormatter */
public static final DateTimeFormatter timeFormatterNanoSeconds = DateTimeFormatter.ofPattern("HH:mm:ss.SSSSSSSSS");
private DateTimeFormatter timeFormatter = timeFormatterTenthSeconds;
private void initialize()
{
......@@ -319,22 +352,25 @@ public class PduRecorder // implements PduReceiver
if(!isRunning())
return;
DateTimeFormatter timeFormatterSeconds = DateTimeFormatter.ofPattern("HH:mm:ss");
DateTimeFormatter timeFormatterMilliseconds = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
LocalTime localTime = LocalTime.now();
String localDateString = LocalDate.now().toString();
String localTimeString = localTime.format(timeFormatterMilliseconds);
LocalTime localTime = LocalTime.now();
long packetReceivedNanoTime = localTime.toNanoOfDay(); // formerly System.nanoTime();
if (startNanoTime == -1)
startNanoTime = packetReceivedNanoTime;
sessionDuration = packetReceivedNanoTime - startNanoTime;
if (isZeroBasedTimeStamp())
{
localDateString = UNDATED;
localTime = LocalTime.ofNanoOfDay(sessionDuration);
}
String localTimeString = localTime.format(timeFormatter);
// DIS timestamp is 8 bytes in length, converted from Java long time into byte array
byte[] timeByteArray = Longs.toByteArray(packetReceivedNanoTime - startNanoTime);
//System.out.println(TRACE_PREFIX + "wrote time "+(packetReceivedNanoTime - startNanoTime)); // debug
byte[] byteBufferSized = Arrays.copyOf(newBuffer, newLength);
DisPduType pduType;
byte[] byteBufferSized = Arrays.copyOf(newBuffer, newLength);
DisPduType pduType = DisPduType.getEnumForValue(Byte.toUnsignedInt(byteBufferSized[2])); // 3rd byte
if (includeHeaders && !headerWritten)
{
......@@ -370,17 +406,17 @@ public class PduRecorder // implements PduReceiver
break;
case ENCODING_PLAINTEXT:
if (isReadableTimeStamp())
if (includesReadableTimeStamp())
{
sb.append(COMMENT_MARKER).append(" ").append(pduType).append(",");
sb.append(localDateString).append(",").append(localTimeString);
sb.append("\n");
}
// Remove square brackets to end up with pure CSV
else sb.append(Arrays.toString(timeByteArray).replace(" ", "").replace("[","").replace("]",""));
// Timestamp bytes, remove square brackets to end up with pure CSV
sb.append(Arrays.toString(timeByteArray).replace(" ", "").replace("[","").replace("]",""));
sb.append(",");
// PDU contents, remove square brackets to end up with pure CSV
sb.append(Arrays.toString(byteBufferSized).replace(" ", "").replace("[","").replace("]",""));
sb.append(" # "); // append comment showing pduType
pduType = DisPduType.getEnumForValue(Byte.toUnsignedInt(byteBufferSized[2])); // 3rd byte
sb.append(pduType);
break;
// TODO test reader still works without extra [square brackets]
......@@ -455,10 +491,26 @@ public class PduRecorder // implements PduReceiver
{
logFileWriter.write(START_COMMENT_MARKER + encodingPduLog + ", " + TRACE_PREFIX + timeStamp + ", DIS capture file, " + logFile.getPath());
((PrintWriter) logFileWriter).println();
if (encodingPduLog.equals(ENCODING_PLAINTEXT) && includesReadableTimeStamp())
{
logFileWriter.write(COMMENT_MARKER + " DisPduType,ReceiptDate,ReceiptTime");
((PrintWriter) logFileWriter).println();
}
if (encodingPduLog.equals(ENCODING_PLAINTEXT))
{
logFileWriter.write(COMMENT_MARKER + " Timestamp(8 bytes),ProtocolVersion,CompatibilityVersion,ExcerciseID,PduType,PduStatus,HeaderLength,PduLength,then PDU-specific data");
((PrintWriter) logFileWriter).println();
}
if (encodingPduLog.equals(ENCODING_PLAINTEXT) && includesReadableTimeStamp())
{
logFileWriter.write(COMMENT_MARKER + " " + "=============================================");
((PrintWriter) logFileWriter).println();
}
}
catch (IOException ex)
catch (IOException ioe)
{
Logger.getLogger(PduRecorder.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(PduRecorder.class.getName()).log(Level.SEVERE, null, ioe);
}
}
......@@ -827,7 +879,7 @@ public class PduRecorder // implements PduReceiver
* Whether to provide date/time in readable form, otherwise use byte array
* @return whether readableTimeStamp is used
*/
public boolean isReadableTimeStamp() {
public boolean includesReadableTimeStamp() {
return readableTimeStamp;
}
......@@ -846,4 +898,50 @@ public class PduRecorder // implements PduReceiver
public long getSessionDuration() {
return sessionDuration;
}
/**
* Whether timestamp values start at zero or time of initial PDU receipt, default value is true
* @return the zeroBasedTimeStamp
*/
public boolean isZeroBasedTimeStamp() {
return zeroBasedTimeStamp;
}
/**
* Set whether timestamp values start at zero or time of initial PDU receipt, default value is true
* @param zeroBasedTimeStamp the zeroBasedTimeStamp to set
*/
public void setZeroBasedTimeStamp(boolean zeroBasedTimeStamp) {
this.zeroBasedTimeStamp = zeroBasedTimeStamp;
}
/**
* Set time format for text logging
* @param timeFormatterChoice enumeration for the new timeFormatter to set
*/
public void setTimeFormatter(TimeFormatterType timeFormatterChoice)
{
switch (timeFormatterChoice)
{
case SECONDS:
timeFormatter = timeFormatterSeconds;
break;
case TENTHSECONDS:
timeFormatter = timeFormatterTenthSeconds;
break;
case HUNDREDTHSECONDS:
timeFormatter = timeFormatterHundredthSeconds;
break;
case MILLISECONDS:
timeFormatter = timeFormatterMilliSeconds;
break;
case MICROSECONDS:
timeFormatter = timeFormatterMicroSeconds;
break;
case NANOSECONDS:
timeFormatter = timeFormatterNanoSeconds;
break;
// no others allowed
}
}
}
AAAAAAAAAAAHAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAAYzvoAHAAICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAA0preQHAAMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAABOA95wHAAQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAABnxmgAHAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACAtXswHAAYDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACb7hEAHAAcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACzzWzQHAAgDAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAADNq8nQHAAkDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAADmjm4wHAAoDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAEFNohAHAAsFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAEgmW1QHAAwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAE8CWIgHAA0FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAFWNXgAHAA4FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFuRyBgHAA8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA==
AAAAAGKewSQHABAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAGlcXvQHABEFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAG+ZdggHABIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAHWhjFwHABMFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAHvs9dgHABQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIJFYKAHABUFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIh53DAHABYFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAI9XTUQHABcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAJWz8UwHABgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAJwi23QHABkEAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAKJppCwHABoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA
AAAAAKlV6CwHABsEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAK/j8FgHABwGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAALZadvAHAB0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAALx6ySwHAB4GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAMM1XUAHAB8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAA=
AAAAAMlzj+wHACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAANAjOwgHACEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAANZ8/fQHACIHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAANyPwqgHACMHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAOLS1DQHACQHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAOllwqwHACUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAO+ICtwHACYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAPZDkSAHACcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAPxEAHgHACgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAQM1eawHACkJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAQnIPlgHACoJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAARB5JwgHACsJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAARbdurQHACwJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAR0/C5wHAC0JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAASPYePgHAC4LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAASpK1xwHAC8LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAATDjePQHADALAAAAAAAAAAAAAAAAAA==
AAAAATbhOyQHADELAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAT0GAgAHADILAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAUMLK4AHADMKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAUkC8gwHADQKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAU8BIAwHADUKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAVVy+7gHADYKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAVv2ikAHADcKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA==
AAAAAWJMDtgHADgKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAWippRAHADkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAW9tr8wHADoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAXW16agHADsKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAX1S8HAHADwKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAYPo36gHAD0KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAYn49mwHAD4KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAZDEz5gHAD8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAZdoZugHAEAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAZ4vQrwHAEEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAaS9U4AHAEIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAaszgKQHAEMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAbGDJbgHAEQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAbgOtXgHAEUCAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAb44kqwHAEYNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAcQ+fxgHAEcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAcpLUrQHAEgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA==
AAAAAAYAWLAHAAICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAAz5hJgHAAMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAABMY7HQHAAQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAABllmPwHAAUDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAB+hRlgHAAYDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACZ1yLQHAAcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACyzmPAHAAgDAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAADM1i1wHAAkDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAADk9rWgHAAoDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAD8v6TQHAAsFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAEWjKLwHAAwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAEu7UFgHAA0FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAFI8YDQHAA4FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFiCcoAHAA8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA==
AAAAAF60AmgHABAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAGT1FjAHABEFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAGsc4OwHABIFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAHGyRRQHABMFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAHfR6qgHABQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAH6FP0QHABUFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIUjA5AHABYFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAIuL6wwHABcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAJGqTAQHABgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAJhnLGAHABkEAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAJ9dIaAHABoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA
AAAAAKVwIbQHABsEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAKwJMnwHABwGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAALIP+nAHAB0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAALiEsiQHAB4GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAL7nHkAHAB8EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAA=
AAAAAMUeP/AHACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAMtCIeQHACEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAANFNpfQHACIHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAANffMugHACMHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAN3ai4QHACQHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAOTk3gwHACUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAOu4fdgHACYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAPIE2egHACcIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAPhxXgAHACgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAP8S4awHACkJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAQUvNNwHACoJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAQuXxBAHACsJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAARGeEogHACwJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAARe/YLgHAC0JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAR4TvywHAC4LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAASU8MEAHAC8LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAStsVBgHADALAAAAAAAAAAAAAAAAAA==
AAAAATGwdxQHADELAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAATfqASwHADILAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAT3wczAHADMKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAUP6EuAHADQKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAUoMGugHADUKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAVARGQwHADYKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAVZ6ZhgHADcKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA==
AAAAAVzQVPAHADgKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAWNGk0QHADkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAWl9YVwHADoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAW+q73wHADsKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAXXUxOAHADwKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAXw5ZjgHAD0KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAYKOSkQHAD4KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAYloT5AHAD8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAY+hP8AHAEAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAZZDpygHAEEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAZ0gqOgHAEIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAaRTNRgHAEMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAap6GogHAEQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAbGHltQHAEUCAAAAAAAAAAAAAAAAAAAAAAAAAAA=
AAAAAbeaskAHAEYNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
AAAAAb4CAFwHAEcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAcQ+hVgHAEgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA==
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment