Build first maven project

- added maven wrapper
- added kst4contest package
- moved tests to src/test/main and added @Test as first step
- moved resources to src/main/resource
This commit is contained in:
Konrad Neitzel
2023-11-10 08:33:17 +01:00
parent af75993474
commit 0e9ba8d42b
56 changed files with 11857 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@@ -0,0 +1,18 @@
# Fleet IDE
.fleet
# Intellij
.idea
*.iml
# Eclipse
.project
.classpath
# Maven
target
debug.out
.DS_Store

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

18
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.2/apache-maven-3.9.2-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

1
SimpleLogFile.txt Normal file
View File

@@ -0,0 +1 @@
do5sa

BIN
lib/javafx-swt.jar Normal file

Binary file not shown.

BIN
lib/javafx.base.jar Normal file

Binary file not shown.

BIN
lib/javafx.controls.jar Normal file

Binary file not shown.

BIN
lib/javafx.fxml.jar Normal file

Binary file not shown.

BIN
lib/javafx.graphics.jar Normal file

Binary file not shown.

BIN
lib/javafx.media.jar Normal file

Binary file not shown.

3
lib/javafx.properties Normal file
View File

@@ -0,0 +1,3 @@
javafx.version=19
javafx.runtime.version=19+11
javafx.runtime.build=11

BIN
lib/javafx.swing.jar Normal file

Binary file not shown.

BIN
lib/javafx.web.jar Normal file

Binary file not shown.

Binary file not shown.

308
mvnw vendored Executable file
View File

@@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd vendored Normal file
View File

@@ -0,0 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

37
pmd-ruleset.xml Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="Custom Java Ruleset"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>
Custom ruleset for Java
</description>
<rule ref="category/java/bestpractices.xml">
<!-- System.println is ok in simple Console App -->
<exclude name="SystemPrintln" />
</rule>
<rule ref="category/java/codestyle.xml" />
<rule ref="category/java/design.xml" />
<rule ref="category/java/design.xml/LoosePackageCoupling">
<properties>
<property name="packages" value="de.kneitzel" />
<!-- <property name="classes" value="" /> -->
</properties>
</rule>
<rule ref="category/java/documentation.xml" />
<rule ref="category/java/errorprone.xml" />
<rule ref="category/java/multithreading.xml" />
<rule ref="category/java/performance.xml" />
<rule ref="category/java/security.xml" />
</ruleset>

460
pom.xml Normal file
View File

@@ -0,0 +1,460 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.x08</groupId>
<artifactId>praktiKST</artifactId>
<version>1.0-SNAPSHOT</version>
<name>praktiKST</name>
<organization>
<name>DO5AMF</name>
</organization>
<url>http://www.x08.de</url>
<packaging>jar</packaging>
<properties>
<!-- Application Properties -->
<link.name>${project.artifactId}</link.name>
<launcher>${project.artifactId}</launcher>
<appName>${project.artifactId}</appName>
<main.class>kst4contest.view.Main</main.class>
<java.version>17</java.version>
<required.maven.version>3.6.3</required.maven.version>
<jar.filename>${project.artifactId}-${project.version}</jar.filename>
<!-- Dependency versions -->
<javafx.version>19.0.2.1</javafx.version>
<jetbrains.annotations.version>24.0.1</jetbrains.annotations.version>
<junit.version>5.10.1</junit.version>
<lombok.version>1.18.30</lombok.version>
<mockito.version>5.7.0</mockito.version>
<sqlite.version>3.43.2.2</sqlite.version>
<!-- Plugin dependencies -->
<maven.clean.plugin>3.3.2</maven.clean.plugin>
<maven.compiler.plugin>3.11.0</maven.compiler.plugin>
<maven.dependency.plugin>3.3.0</maven.dependency.plugin>
<maven.deploy.plugin>3.1.1</maven.deploy.plugin>
<maven.enforcer.plugin>3.4.1</maven.enforcer.plugin>
<maven.install.plugin>3.1.1</maven.install.plugin>
<maven.jar.plugin>3.3.0</maven.jar.plugin>
<maven.resources.plugin>3.3.1</maven.resources.plugin>
<maven.site.plugin>4.0.0-M11</maven.site.plugin>
<maven.surfire.plugin>3.2.2</maven.surfire.plugin>
<maven.wrapper.plugin>3.2.0</maven.wrapper.plugin>
<moditect.maven.plugin>1.0.0.RC2</moditect.maven.plugin>
<jpackage.maven.plugin>0.1.3</jpackage.maven.plugin>
<maven.pmd.version>3.21.2</maven.pmd.version>
<pmd.version>6.55.0</pmd.version>
<codehaus.version.plugin>2.16.1</codehaus.version.plugin>
<javafx.maven.plugin>0.0.8</javafx.maven.plugin>
<spotbugs.maven.plugin>4.8.1.0</spotbugs.maven.plugin>
<spotbugs.version>4.8.1</spotbugs.version>
<!-- other properties -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>
<maven.plugin.validation>VERBOSE</maven.plugin.validation>
</properties>
<dependencies>
<!-- JavaFX dependencies -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>${sqlite.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<!-- Dependency used for @NotNull / @Nullable -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>${jetbrains.annotations.version}</version>
<scope>compile</scope>
</dependency>
<!--
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>javax.xml.parsers</groupId>
<artifactId>jaxp-api</artifactId>
<version>1.4.5</version>
</dependency>
-->
</dependencies>
<build>
<finalName>${jar.filename}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-wrapper-plugin</artifactId>
<version>${maven.wrapper.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven.enforcer.plugin}</version>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>${required.maven.version}</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin}</version>
<configuration>
<release>${java.version}</release>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven.clean.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${maven.deploy.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${maven.install.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven.jar.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>${maven.site.plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surfire.plugin}</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>${spotbugs.maven.plugin}</version>
<dependencies>
<!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>${spotbugs.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<!-- spotbugs does not stop build when violations are found -->
<goal>spotbugs</goal>
<!-- check stops the build when violations are found -->
<!-- <goal>check</goal> -->
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>${maven.pmd.version}</version>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-javascript</artifactId>
<version>${pmd.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-jsp</artifactId>
<version>${pmd.version}</version>
</dependency>
</dependencies>
<configuration>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<minimumTokens>100</minimumTokens>
<targetJdk>${java.version}</targetJdk>
<linkXRef>false</linkXRef>
<rulesets>
<ruleset>pmd-ruleset.xml</ruleset>
</rulesets>
</configuration>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<!-- pmd does not stop build when violations are found -->
<goal>pmd</goal>
<!-- check stops the build when violations are found -->
<!-- <goal>check</goal> -->
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${codehaus.version.plugin}</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>display-dependency-updates</goal>
<goal>display-plugin-updates</goal>
<goal>display-property-updates</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- JavaFX Plugin to start application -->
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>${javafx.maven.plugin}</version>
<configuration>
<mainClass>${main.class}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<!-- Profile that adds JLink and JPackage runs.
Add -PImage or -DImage to use this profile.
-->
<profile>
<id>Image</id>
<activation>
<property>
<name>Image</name>
</property>
</activation>
<build>
<plugins>
<!-- Copy dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven.dependency.plugin}</version>
<executions>
<!-- erstmal Abhängigkeiten für den Class-Path kopieren -->
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
<!-- dazu noch das Projekt-JAR -->
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>${project.packaging}</type>
<destFileName>${project.build.finalName}.jar</destFileName>
</artifactItem>
</artifactItems>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<version>${jpackage.maven.plugin}</version>
<configuration>
<name>${appName}</name>
<type>IMAGE</type>
<modulepath>
<dependencysets>
<dependencyset>
<includenames>
<includename>javafx\..*</includename>
</includenames>
</dependencyset>
</dependencysets>
</modulepath>
<addmodules>
<addmodule>javafx.controls</addmodule>
<addmodule>javafx.graphics</addmodule>
<addmodule>javafx.fxml</addmodule>
<addmodule>javafx.web</addmodule>
<addmodule>java.sql</addmodule>
</addmodules>
<mainclass>${main.class}</mainclass>
<input>${project.build.directory}/modules</input>
<mainjar>${jar.filename}.jar</mainjar>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>jpackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,202 @@
package kst4contest.controller;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NoRouteToHostException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.TimerTask;
import javafx.collections.ObservableList;
import kst4contest.model.ChatMember;
public class AirScoutPeriodicalAPReflectionInquirerTask extends TimerTask {
private ChatController client;
public AirScoutPeriodicalAPReflectionInquirerTask(ChatController client) {
this.client = client;
}
@Override
public void run() {
Thread.currentThread().setName("AirscoutPeriodicalReflectionInquirierTask");
//TODO: Manage prefixes kst and as via preferences file and instance
//TODO: Check if locator is changeable via the preferences object, need to be correct if it changes
DatagramSocket dsocket;
String prefix_asSetpath ="ASSETPATH: \"KST\" \"AS\" ";
String prefix_asWatchList = "ASWATCHLIST: \"KST\" \"AS\" ";
String bandString = "1440000";
String myCallAndMyLocString = this.client.getChatPreferences().getLoginCallSign() + "," + this.client.getChatPreferences().getLoginLocator();
String suffix = ""; //"FOREIGNCALL,FOREIGNLOC " -- dont forget the space at the end!!!
String asWatchListString = prefix_asWatchList + bandString + "," + myCallAndMyLocString;
String asWatchListStringSuffix = asWatchListString;
String host = "255.255.255.255";
int port = 9872;
// byte[] message = "ASSETPATH: \"KST\" \"AS\" 1440000,DO5AMF,JN49GL,OK1MZM,JN89IW ".getBytes(); Original, ging
InetAddress address;
/**
* Iterate over chatmemberlist and asking airscout for plane reflection information
* To avoid a concurrentmodifyexception, we have to convert the original list to an array at first
* since the iterator brakes if the list changing during the iteration time
*/
ObservableList<ChatMember> praktiKSTActiveUserList = this.client.getLst_chatMemberList();
ChatMember[] ary_threadSafeChatMemberArray = new ChatMember[praktiKSTActiveUserList.size()];
praktiKSTActiveUserList.toArray(ary_threadSafeChatMemberArray);
for (ChatMember i : ary_threadSafeChatMemberArray) {
suffix = i.getCallSign() + "," + i.getQra() + " ";
//
String queryStringToAirScout = "";
queryStringToAirScout += prefix_asSetpath + bandString + "," + myCallAndMyLocString + "," + suffix;
byte[] queryStringToAirScoutMSG = queryStringToAirScout.getBytes();
try {
address = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(queryStringToAirScoutMSG, queryStringToAirScoutMSG.length, address, port);
dsocket = new DatagramSocket();
dsocket.setBroadcast(true);
dsocket.send(packet);
dsocket.close();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoRouteToHostException e) {
e.printStackTrace();
}
catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println("[ASUDPTask, info:] sent query " + queryStringToAirScout);
asWatchListStringSuffix += "," + i.getCallSign() + "," + i.getQra();
}
// for (Iterator iterator = praktiKSTActiveUserList.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
//
// suffix = chatMember.getCallSign() + "," + chatMember.getQra() + " ";
//
// String queryStringToAirScout = "";
//
// queryStringToAirScout += prefix_asSetpath + bandString + "," + myCallAndMyLocString + "," + suffix;
//
// byte[] queryStringToAirScoutMSG = queryStringToAirScout.getBytes();
//
// try {
// address = InetAddress.getByName("255.255.255.255");
// DatagramPacket packet = new DatagramPacket(queryStringToAirScoutMSG, queryStringToAirScoutMSG.length, address, port);
// dsocket = new DatagramSocket();
// dsocket.setBroadcast(true);
// dsocket.send(packet);
// dsocket.close();
// } catch (UnknownHostException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// } catch (SocketException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
//// System.out.println("[ASUDPTask, info:] sent query " + queryStringToAirScout);
//
// asWatchListStringSuffix += "," + chatMember.getCallSign() + "," + chatMember.getQra();
//
// }}
// for (Iterator iterator = praktiKSTActiveUserList.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
//
// suffix = chatMember.getCallSign() + "," + chatMember.getQra() + " ";
//
// String queryStringToAirScout = "";
//
// queryStringToAirScout += prefix_asSetpath + bandString + "," + myCallAndMyLocString + "," + suffix;
//
// byte[] queryStringToAirScoutMSG = queryStringToAirScout.getBytes();
//
// try {
// address = InetAddress.getByName("255.255.255.255");
// DatagramPacket packet = new DatagramPacket(queryStringToAirScoutMSG, queryStringToAirScoutMSG.length, address, port);
// dsocket = new DatagramSocket();
// dsocket.setBroadcast(true);
// dsocket.send(packet);
// dsocket.close();
// } catch (UnknownHostException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// } catch (SocketException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
//// System.out.println("[ASUDPTask, info:] sent query " + queryStringToAirScout);
//
// asWatchListStringSuffix += "," + chatMember.getCallSign() + "," + chatMember.getQra();
//
// }
/**
* As next we will set the ASWatchlist. All stations in chat will be watched by airscout causing following code.\n\n
* ASWATCHLIST: "KST" "AS" 4320000,DO5AMF,JN49GL,DF9QX,JO42HD,DG2KBC,JN58MI,DJ0PY,JO32MF,DL1YDI,JO42FA,DL6BF,JO32QI,F1NZC,JN15MR,F4TXU,JN23CX,F5GHP,IN96LE,F6HTJ,JN12KQ,G0GGG,IO81VE,G0JCC,IO82MA,G0JDL,JO02SI,G0MBL,JO01QH,G4AEP,IO91MB,G4CLA,IO92JL,G4DCV,IO91OF,G4LOH,IO70JC,G4MKF,IO91HJ,G4TRA,IO81WN,G8GXP,IO93FQ,G8VHI,IO92FM,GW0RHC,IO71UN,HA4ND,JN97MJ,I5/HB9SJV/P,JN52JS,IW2DAL,JN45NN,OK1FPR,JO80CE,OK6M,JN99CR,OV3T,JO46CM,OZ2M,JO65FR,PA0V,JO33II,PA2RU,JO32LT,PA3DOL,JO22MT,PA9R,JO22JK,PE1EVX,JO22MP,S51AT,JN75GW,SM7KOJ,JO66ND,SP9TTG,JO90KW<4B>
* The watchlist-String is bult by the for loop which builds the AP queries
*/
asWatchListStringSuffix += " ";
byte[] queryStringToAirScoutMSG = asWatchListStringSuffix.getBytes();
try {
address = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(queryStringToAirScoutMSG, queryStringToAirScoutMSG.length, address, port);
dsocket = new DatagramSocket();
dsocket.setBroadcast(true);
dsocket.send(packet);
dsocket.close();
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println("[ASUDPTask, info:] set watchlist: " + asWatchListStringSuffix);
}
}

View File

@@ -0,0 +1,13 @@
package kst4contest.controller;
import kst4contest.view.Main;
public class AppRunner {
public static void main(String[] args) {
Main.main(args);
}
}

View File

@@ -0,0 +1,63 @@
package kst4contest.controller;
import java.util.TimerTask;
import kst4contest.model.ChatMessage;
/**
* This class is for sending beacons intervalled to the public chat. Gets all
* preferences and instances via the Chatpreferences-object of the
* Chatcontroller.
* <br/><br/>
* The task will be runned out of the singleton ChatController instance in an
* intervall as specified by the Chatpreferences-instance (typically as
* configured in the xml file.
*
*
* @author prakt
*
*/
public class BeaconTask extends TimerTask {
private ChatController chatController;
public BeaconTask(ChatController client) {
this.chatController = client;
}
@Override
public void run() {
Thread.currentThread().setName("BeaconTask");
ChatMessage beaconMSG = new ChatMessage();
String replaceVariables = this.chatController.getChatPreferences().getBcn_beaconText();
// replaceVariables = bcn_beaconText;
replaceVariables = replaceVariables.replaceAll("MYQRG", this.chatController.getChatPreferences().getMYQRG().getValue());
replaceVariables = replaceVariables.replaceAll("MYCALL", this.chatController.getChatPreferences().getLoginCallSign());
replaceVariables = replaceVariables.replaceAll("MYLOCATOR", this.chatController.getChatPreferences().getLoginLocator());
replaceVariables = replaceVariables.replaceAll("MYQTF", this.chatController.getChatPreferences().getActualQTF().getValue() + "");
beaconMSG.setMessageText(
"MSG|" + this.chatController.getChatPreferences().getLoginChatCategory().getCategoryNumber() + "|0|" + replaceVariables + "|0|");
beaconMSG.setMessageDirectedToServer(true);
// System.out.println("########### " + replaceVariables);
if (this.chatController.getChatPreferences().isBcn_beaconsEnabled() ) {
System.out.println(new Utils4KST().time_generateCurrentMMDDhhmmTimeString()
+ " [BeaconTask, Info]: Sending CQ: " + beaconMSG.getMessageText());
this.chatController.getMessageTXBus().add(beaconMSG);
} else {
//do nothing, CQ is disabled
}
}
}

View File

@@ -0,0 +1,973 @@
package kst4contest.controller;
import java.net.*;
import java.sql.SQLException;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.LinkedBlockingQueue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import kst4contest.model.ChatCategory;
import kst4contest.model.ChatMember;
import kst4contest.model.ChatMessage;
import kst4contest.model.ChatPreferences;
import kst4contest.model.ClusterMessage;
import java.io.*;
/**
*
* Central Chat kst4contest.controller. Instantiate only one time per category of kst Chat.
* Provides complex data types for communication with the gui and drives the
* threads of telnet tx, telnet rx and message processing. <br/>
* <b>SINGLETON</b>
*
*/
public class ChatController {
/**
* Chat selection ? 50/70 MHz..............1 144/432 MHz............2
* Microwave..............3 EME/JT65...............4 Low Band...............5 50
* MHz IARU Region 3...6 50 MHz IARU Region 2...7 144/432 MHz IARU R 2...8
* 144/432 MHz IARU R 3...9 kHz (2000-630m).......10 Warc (30,17,12m)......11 28
* MHz................12 Your choice :
*
*/
// private int category = ChatCategory.VUHF;
private ChatPreferences chatPreferences;
private ChatCategory category;
boolean connectedAndLoggedIn;
boolean connectedAndNOTLoggedIn;
boolean disconnected;
boolean disconnectionPerformedByUser = false;
public boolean isDisconnectionPerformedByUser() {
return disconnectionPerformedByUser;
}
public void setDisconnectionPerformedByUser(boolean disconnectionPerformedByUser) {
this.disconnectionPerformedByUser = disconnectionPerformedByUser;
}
public String getChatState() {
return chatState;
}
public void setChatState(String chatState) {
this.chatState = chatState;
}
public boolean isConnectedAndLoggedIn() {
return connectedAndLoggedIn;
}
public void setConnectedAndLoggedIn(boolean connectedAndLoggedIn) {
this.connectedAndLoggedIn = connectedAndLoggedIn;
}
public boolean isConnectedAndNOTLoggedIn() {
return connectedAndNOTLoggedIn;
}
public void setConnectedAndNOTLoggedIn(boolean connectedAndNOTLoggedIn) {
this.connectedAndNOTLoggedIn = connectedAndNOTLoggedIn;
}
public boolean isDisconnected() {
return disconnected;
}
public void setDisconnected(boolean disconnected) {
this.disconnected = disconnected;
}
/**
* Handles the disconnect of either the chat (Case DISCONNECTONLY) or the
* complete application life including all threads (case CLOSEALL)
*
* @param action: "CLOSEALL" or "DISCONNECTONLYCHAT", on application close event
* (Settings Window closed), Disconnect on Disconnect-Button
* clicked (new connection may follow)
*/
public void disconnect(String action) {
this.setDisconnectionPerformedByUser(true);
if (action.equals("CLOSEALL")) {
this.setDisconnected(true);
this.setConnectedAndLoggedIn(false);
this.setConnectedAndNOTLoggedIn(false);
// disconnect telnet and kill all sockets and connections
keepAliveTimer.cancel();
keepAliveTimer.purge();
ChatMessage killThreadPoisonPillMsg = new ChatMessage();
killThreadPoisonPillMsg.setMessageText("POISONPILL_KILLTHREAD");
killThreadPoisonPillMsg.setMessageSenderName("POISONPILL_KILLTHREAD");
messageRXBus.clear();
messageTXBus.clear();
messageRXBus.add(killThreadPoisonPillMsg); //kills messageprocessor
messageTXBus.add(killThreadPoisonPillMsg); //kills writethread
writeThread.interrupt();
readThread.interrupt();
beaconTimer.purge();
beaconTimer.cancel();
ASQueryTimer.purge();
ASQueryTimer.cancel();
socketCheckTimer.purge();
socketCheckTimer.cancel();
userActualizationtimer.purge();
userActualizationtimer.cancel();
userActualizationtimer.purge();
userActualizationtimer.cancel();
// consoleReader.interrupt();
messageProcessor.interrupt();
readUDPbyUCXThread.interrupt();
airScoutUDPReaderThread.interrupt();
dbHandler.closeDBConnection();
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
} else if (action.equals("JUSTDSICCAUSEPWWRONG")){
this.setDisconnected(true);
this.setConnectedAndLoggedIn(false);
this.setConnectedAndNOTLoggedIn(true);
// disconnect telnet and kill all sockets and connections
keepAliveTimer.cancel();
keepAliveTimer.purge();
ChatMessage killThreadPoisonPillMsg = new ChatMessage();
killThreadPoisonPillMsg.setMessageText("POISONPILL_KILLTHREAD");
killThreadPoisonPillMsg.setMessageSenderName("POISONPILL_KILLTHREAD");
messageRXBus.clear();
messageTXBus.clear();
messageRXBus.add(killThreadPoisonPillMsg); //kills messageprocessor
messageTXBus.add(killThreadPoisonPillMsg); //kills writethread
writeThread.interrupt();
readThread.interrupt();
beaconTimer.purge();
beaconTimer.cancel();
ASQueryTimer.purge();
ASQueryTimer.cancel();
socketCheckTimer.purge();
socketCheckTimer.cancel();
userActualizationtimer.purge();
userActualizationtimer.cancel();
userActualizationtimer.purge();
userActualizationtimer.cancel();
// consoleReader.interrupt();
messageProcessor.interrupt();
readUDPbyUCXThread.interrupt();
airScoutUDPReaderThread.interrupt();
dbHandler.closeDBConnection();
}
}
// private String userName = "DO5AMF";
// private String password = "uxskezcj";
private String userName;
private String password;
private String showedName;
private String qra;
private String chatState;
private String hostname = "109.90.0.130";
private String praktiKSTVersion = "wtKST 3.1.4.6";
// private String praktiKSTVersion = "praktiKST 1.0";
private String praktiKSTVersionInfo = "2022-10 - 2022-12\ndeveloped by DO5AMF, Marc\nContact: praktimarc@gmail.com\nDonations via paypal are welcome";
private int port = 23001; // kst4contest.test 4 23001
private ReadUDPbyUCXMessageThread readUDPbyUCXThread;
private WriteThread writeThread;
private ReadThread readThread;
private InputReaderThread consoleReader;
private ChatMember ownChatMemberObject; // Todo: set at startup
private ChatController chatController;
private MessageBusManagementThread messageProcessor;
private ReadUDPbyAirScoutMessageThread airScoutUDPReaderThread;
private TimerTask userActualizationTask;
private TimerTask keepAliveMessageSenderTask;
private LinkedBlockingQueue<ChatMessage> messageRXBus; // Queue in which all Chatmessages are buffered, sources are
// read- and write-thread
private LinkedBlockingQueue<ChatMessage> messageTXBus; // Queue in which all Chatmessages are buffered, sources are
// read- and write-thread
private String observedSendThisMessageString;
private DBController dbHandler;
private Socket socket;
private Timer userActualizationtimer;
private Timer keepAliveTimer;
private Timer beaconTimer;
private Timer ASQueryTimer;
private Timer socketCheckTimer;
// ******All abstract types below here are used by the messageprocessor!
// ***************
// private Hashtable<String, ChatMember> chatMemberTable = new Hashtable<String, ChatMember>();
// private HashMap<String, ChatMember> chatMemberTable = new HashMap<String, ChatMember>();
// private Hashtable<String, ChatMember> dXClusterMemberTable = new Hashtable<String, ChatMember>();
private ObservableList<ChatMessage> lst_toAllMessageList = FXCollections.observableArrayList(); // directed to all
// (beacon)
private ObservableList<ChatMessage> lst_toMeMessageList = FXCollections.observableArrayList(); // directed to my
// call
private ObservableList<ChatMessage> lst_toOtherMessageList = FXCollections.observableArrayList(); // directed to a
// call but not
// mine
private ObservableList<ChatMember> chatMemberList = FXCollections.observableArrayList(); // List of active stations
// in chat
private ObservableList<ChatMember> lst_chatMemberList = FXCollections.synchronizedObservableList(chatMemberList); // List
// of
// active
// stations
// in
// chat
private ObservableList<ClusterMessage> lst_clusterMemberList = FXCollections.observableArrayList();
private ObservableList<ChatMember> lst_DBBasedWkdCallSignList = FXCollections.observableArrayList();
// private HashMap<String, ChatMember> map_ucxLogInfoWorkedCalls = new HashMap<String, ChatMember>(); //Destination of ucx-log worked-messages
// ******************************************************************************************************************************************
/**
* checks if the callsign-String of a given chatmember instance and a given list
* instance is in the list. If yes, returns the index in the List, <b>if not,
* returns -1.</b>
*
* @param lookForThis
* @return Integer (index), -1 for not found
*/
public int checkListForChatMemberIndexByCallSign(ChatMember lookForThis) {
if (lookForThis == null) {
// System.out.println("[ChatCtrl] ERROR: null Value for Chatmember detected! Member cannot be in the list!");
return -1;
} else if (lookForThis.getCallSign() == null) {
System.out.println("[ChatCtrl] ERROR: null Value in Callsign detected! Member cannot be in the list!");
return -1;
}
for (Iterator iterator = lst_chatMemberList.iterator(); iterator.hasNext();) {
ChatMember chatMember = (ChatMember) iterator.next();
if (chatMember.getCallSign().equals(lookForThis.getCallSign())) {
// System.out
// .println("MSGBUSHELPER: Found " + chatMember.getCallSign() + " at " + lst_chatMemberList.indexOf(chatMember));
return lst_chatMemberList.indexOf(chatMember);
} else {
}
}
/**
* At this point we know, the callsign is not active in the chat.
*/
// System.out
// .println("[ChatCtrl, ERROR:] ChecklistForChatMemberIndexByCallsign: " + lookForThis.getCallSign() + "\n" + "List: ");
// for (Iterator iterator = lst_chatMemberList.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
// System.out.println(lst_chatMemberList.indexOf(lookForThis) + ": " + chatMember.getCallSign());
// }
return -1;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public void setMessageTXBus(LinkedBlockingQueue<ChatMessage> messageTXBus) {
this.messageTXBus = messageTXBus;
}
public String getPraktiKSTVersion() {
return praktiKSTVersion;
}
public void setPraktiKSTVersion(String praktiKSTVersion) {
this.praktiKSTVersion = praktiKSTVersion;
}
public String getPraktiKSTVersionInfo() {
return praktiKSTVersionInfo;
}
public void setPraktiKSTVersionInfo(String praktiKSTVersionInfo) {
this.praktiKSTVersionInfo = praktiKSTVersionInfo;
}
// public HashMap getMap_ucxLogInfoWorkedCalls() {
// return map_ucxLogInfoWorkedCalls;
// }
// public void setMap_ucxLogInfoWorkedCalls(HashMap map_ucxLogInfoWorkedCalls) {
// this.map_ucxLogInfoWorkedCalls = map_ucxLogInfoWorkedCalls;
// }
public ObservableList<ChatMember> getLst_chatMemberList() {
return lst_chatMemberList;
}
public ObservableList<ChatMember> getLst_DBBasedWkdCallSignList() {
return lst_DBBasedWkdCallSignList;
}
public void setLst_DBBasedWkdCallSignList(ObservableList<ChatMember> lst_DBBasedWkdCallSignList) {
this.lst_DBBasedWkdCallSignList = lst_DBBasedWkdCallSignList;
}
public void setLst_chatMemberList(ObservableList<ChatMember> lst_chatMemberList) {
this.lst_chatMemberList = lst_chatMemberList;
}
public ObservableList<ClusterMessage> getLst_clusterMemberList() {
return lst_clusterMemberList;
}
public void setLst_clusterMemberList(ObservableList<ClusterMessage> lst_clusterMemberList) {
this.lst_clusterMemberList = lst_clusterMemberList;
}
public ObservableList<ChatMessage> getLst_toAllMessageList() {
return lst_toAllMessageList;
}
public void setLst_toAllMessageList(ObservableList<ChatMessage> lst_toAllMessageList) {
this.lst_toAllMessageList = lst_toAllMessageList;
}
public ObservableList<ChatMessage> getLst_toMeMessageList() {
return lst_toMeMessageList;
}
public void setLst_toMeMessageList(ObservableList<ChatMessage> lst_toMeMessageList) {
this.lst_toMeMessageList = lst_toMeMessageList;
}
public ObservableList<ChatMessage> getLst_toOtherMessageList() {
return lst_toOtherMessageList;
}
public void setLst_toOtherMessageList(ObservableList<ChatMessage> lst_toOtherMessageList) {
this.lst_toOtherMessageList = lst_toOtherMessageList;
}
public LinkedBlockingQueue<ChatMessage> getMessageTXBus() {
return messageTXBus;
}
public ChatController() {
super();
category = new ChatCategory(2);
ownChatMemberObject = new ChatMember();
ownChatMemberObject.setCallSign(userName);
ownChatMemberObject.setName(showedName);
ownChatMemberObject.setQra(qra);
// this.category = ChatCategory.VUHF;
this.userName = ownChatMemberObject.getName();
// this.password = "uxskezcj";
this.hostname = "www.on4kst.info";
this.port = port;
}
/**
* This constructor is used by the Main()-Class of the praktiKST javaFX-gui.
*
* @param setCategory
* @param setOwnChatMemberObject
*/
public ChatController(ChatMember setOwnChatMemberObject) {
super();
chatPreferences = new ChatPreferences();
chatPreferences.readPreferencesFromXmlFile(); // set the praktikst Prefs by file or default if file is corrupted
category = chatPreferences.getLoginChatCategory();
this.userName = chatPreferences.getLoginCallSign();
this.password = chatPreferences.getLoginPassword();
// category = setCategory;
ownChatMemberObject = setOwnChatMemberObject;
// this.userName = ownChatMemberObject.getName();
// this.password = ownChatMemberObject.getPassword();
this.hostname = "www.on4kst.info";
this.port = port;
}
public ChatPreferences getChatPreferences() {
return chatPreferences;
}
public void setChatPreferences(ChatPreferences chatPreferences) {
this.chatPreferences = chatPreferences;
}
public ChatMember getownChatMemberObject() {
return ownChatMemberObject;
}
public void setOwnCall(ChatMember ownCall) {
this.ownChatMemberObject = ownCall;
}
public LinkedBlockingQueue<ChatMessage> getMessageRXBus() {
return messageRXBus;
}
public void setMessageRXBus(LinkedBlockingQueue<ChatMessage> messageBus) {
this.messageRXBus = messageBus;
}
public WriteThread getWriteThread() {
return writeThread;
}
public void setWriteThread(WriteThread writeThread) {
this.writeThread = writeThread;
}
public ReadThread getReadThread() {
return readThread;
}
public void setReadThread(ReadThread readThread) {
this.readThread = readThread;
}
public ChatCategory getCategory() {
return category;
}
public void setCategory(ChatCategory category) {
this.category = category;
}
// public void setChatMemberTable(Hashtable<String, ChatMember> chatMemberTable) {
// this.chatMemberTable = chatMemberTable;
// }
//
// public void setChatMemberTable(HashMap<String, ChatMember> chatMemberTable) {
// this.chatMemberTable = chatMemberTable;
// }
public DBController getDbHandler() {
return dbHandler;
}
public void setDbHandler(DBController dbHandler) {
this.dbHandler = dbHandler;
}
public void execute() throws InterruptedException, IOException {
chatController = this;
// This block constructs a sample message
// ChatMessage Test = new ChatMessage();
// Test.setMessage("kst4contest.test");
// Test.setMessageDirectedToCommunity(false);
// Test.setMessageGeneratedTime(new Utils4KST().time_convertEpochToReadable("1664669836"));
// Test.setMessageSenderName("marc");
// Test.setMessageText("test2");
// Test.setSender(ownChatMemberObject);
// getLst_toAllMessageList().add(Test);
try {
dbHandler = new DBController();
messageRXBus = new LinkedBlockingQueue<ChatMessage>();
messageTXBus = new LinkedBlockingQueue<ChatMessage>();
// messageBus.add("");
socket = new Socket(hostname, port);
System.out.println("Connected to the chat server: " + socket.isConnected());
// consoleReader = new InputReaderThread(this);
// consoleReader.start();
readThread = new ReadThread(socket, this);
readThread.setName("ReadThread-telnetreader");
readThread.start();
writeThread = new WriteThread(socket, this);
writeThread.setName("Writethread-telnetwriter");
writeThread.start();
readUDPbyUCXThread = new ReadUDPbyUCXMessageThread(12060, this);
readUDPbyUCXThread.setName("readUDPbyUCXThread");
readUDPbyUCXThread.start();
messageProcessor = new MessageBusManagementThread(this);
messageProcessor.setName("messagebusManagementThread");
messageProcessor.start();
airScoutUDPReaderThread = new ReadUDPbyAirScoutMessageThread(9872, this, "AS", "KST");
airScoutUDPReaderThread.setName("airscoutudpreaderThread");
airScoutUDPReaderThread.start();
userActualizationtimer = new Timer();
userActualizationtimer.schedule(new UserActualizationTask(this), 4000, 60000);// TODO: Temporary
// userlistoutput
// with
// known qrgs
keepAliveTimer = new Timer();
keepAliveTimer.schedule(new keepAliveMessageSenderTask(this), 4000, 60000);// TODO: Temporary
// userlistoutput
// with
// keepAliveMessageSenderTask = new keepAliveMessageSenderTask(this);
// keepAliveMessageSenderTask.run();
// userActualizationTask = new UserActualizationTask(this); // kst4contest.test 4 23001
// userActualizationTask.run();// kst4contest.test 4 23001
this.setConnectedAndLoggedIn(true);
/**
* The CQ-beacon-Task will be executed every time but checks for itself whether
* CQ messages are enabled or not
*/
// Timer beaconTimer;
beaconTimer = new Timer();
beaconTimer.schedule(new BeaconTask(this), 10000,
this.getChatPreferences().getBcn_beaconIntervalInMinutes() * 60000);
// 60000 * intervalInMinutes = IntervalInMillis
/**
* The AS querier task will be executed every time but checks for itself whether
* AS usage is enabled or not
*/
// Timer ASQueryTimer;
ASQueryTimer = new Timer();
ASQueryTimer.schedule(new AirScoutPeriodicalAPReflectionInquirerTask(this), 10000, 5000);
// 60000 * intervalInMinutes = IntervalInMillis
/**
* Check if socket works
*/
// Timer socketCheckTimer;
socketCheckTimer = new Timer();
socketCheckTimer.schedule(new TimerTask() {
@Override
public void run() {
// System.out.println("[Chatcontroller, info: ] periodical socketcheck");
Thread.currentThread().setName("SocketcheckTimer");
if (!socket.isConnected() || socket.isClosed()) {
try {
messageRXBus.clear();
messageTXBus.clear();
socket.close();
chatController.setConnectedAndLoggedIn(false);
chatController.getLst_chatMemberList().clear();
// messageProcessor.interrupt();
// chatController.getReadThread().interrupt();
// chatController.getWriteThread().interrupt();
// keepAliveTimer.wait();
// chatController.getstat
System.out.println("[Chatcontroller, Warning: ] Socket closed or disconnected");
ChatMessage killThreadPoisonPillMsg = new ChatMessage();
killThreadPoisonPillMsg.setMessageText("POISONPILL_KILLTHREAD");
killThreadPoisonPillMsg.setMessageSenderName("POISONPILL_KILLTHREAD");
ChatMessage killThreadPoisonPillMsg2 = new ChatMessage();
killThreadPoisonPillMsg2.setMessageText("POISONPILL_KILLTHREAD");
killThreadPoisonPillMsg2.setMessageSenderName("POISONPILL_KILLTHREAD");
messageRXBus.add(killThreadPoisonPillMsg);
messageTXBus.add(killThreadPoisonPillMsg2);
chatController.getReadThread().interrupt();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/**
* The next block will attempt to reinit the chatclient after accidental
* disconnection
*/
try {
if (!disconnectionPerformedByUser) {
messageRXBus.clear();
messageTXBus.clear();
socket = new Socket(hostname, port);
// readThread.interrupt();
chatController.setReadThread(new ReadThread(socket, chatController));
chatController.readThread.start();
chatController.setWriteThread(new WriteThread(socket, chatController));
chatController.writeThread.start();
messageProcessor = new MessageBusManagementThread(chatController);
messageProcessor.start();
// chatController.setMessageProcessor= new MessageBusManagementThread(chatController);
// messageProcessor.start();
System.out.println("[Chatcontroller, info: initialized new socket, is connected? ] "
+ socket.isConnected() + " " + socket.isClosed());
initialize23001();
Timer waitABit = new Timer();
socketCheckTimer.schedule(new TimerTask() {
@Override
public void run() {
Thread.currentThread().setName("waiting");
if (socket.isConnected()) {
chatController.setConnectedAndLoggedIn(true);
}
//just take a breath
}
}, 5000);
// keepAliveTimer.notify();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, 10000, 10000);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O Error: " + ex.getMessage());
}
while (readThread == null) {
// do nothing, wait!
System.out.println("Reader not ready.");
}
// initialize();//kst4contest.test 4 23001
initialize23001(); // init Chatcontroller for using port 23001
}
public long getCurrentEpochTime() {
OffsetDateTime currentTimeInUtc = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(currentTimeInUtc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm X")));
long millisecondsSinceEpoch = currentTimeInUtc.toInstant().toEpochMilli() / 1000;
// System.out.println(millisecondsSinceEpoch);
return millisecondsSinceEpoch;
}
/**
* Setting the initial parameters at the chat via port 23001 <br/>
* <br/>
* <b>Login parameter format is like that: </b><br/>
* LOGINC|do5amf|uxskezcj|2|wtKST 3.1.4.6|25|0|1|1663879818|0| <br/>
* SDONE|2| <br/>
*
* @throws InterruptedException
* @throws IOException
*/
public void initialize23001() throws InterruptedException, IOException {
messageTXBus.clear();
ChatMessage message = new ChatMessage();
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Thread.currentThread().setName("LoginStringTimer");
String loginString = "";
loginString = "LOGINC|" + chatPreferences.getLoginCallSign() + "|" + chatPreferences.getLoginPassword()
+ "|" + chatPreferences.getLoginChatCategory().getCategoryNumber() + "|" + praktiKSTVersion
+ "|25|0|1|" + getCurrentEpochTime() + "|0|";
// System.out.println(loginString);
ChatMessage message = new ChatMessage();
message.setMessageText(loginString);
message.setMessageDirectedToServer(true);
getMessageTXBus().add(message);
}
}, 2000);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Thread.currentThread().setName("SDONEStringTimer");
ChatMessage message = new ChatMessage();
message.setMessageText("SDONE|" + chatPreferences.getLoginChatCategory().getCategoryNumber() + "|\r");
message.setMessageDirectedToServer(true);
getMessageTXBus().add(message);
}
}, 3000);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Thread.currentThread().setName("SETLOCTIMER");
ChatMessage message = new ChatMessage();
message.setMessageText("MSG|" + chatPreferences.getLoginChatCategory().getCategoryNumber()
+ "|0|/SETLOC " + chatPreferences.getLoginLocator() + "|0|\r");
message.setMessageDirectedToServer(true);
getMessageTXBus().add(message);
}
}, 4000);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Thread.currentThread().setName("SETNAMETIMER");
ChatMessage message = new ChatMessage();
message.setMessageText("MSG|" + chatPreferences.getLoginChatCategory().getCategoryNumber()
+ "|0|/SETNAME " + chatPreferences.getLoginName() + "|0|\r");
message.setMessageDirectedToServer(true);
getMessageTXBus().add(message);
}
}, 5000);
new Timer().schedule(new TimerTask() {
HashMap<String, ChatMember> getWorkedDataFromDb;
@Override
public void run() {
Thread.currentThread().setName("fetchWorkedFromDBTimer");
try {
getWorkedDataFromDb = dbHandler.fetchChatMemberWkdDataFromDB();
} catch (SQLException e) {
System.out.println("[Chatctrl, Error: ] got no worked data from DB due to communication error");
}
for (Iterator iterator = getLst_chatMemberList().iterator(); iterator.hasNext();) {
ChatMember chatMember = (ChatMember) iterator.next();
System.out.println("[Chatctrl]: Marking ChatMembers wkd information: "
+ getWorkedDataFromDb.get(chatMember.getCallSign()).getCallSign());
chatMember.setWorked(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked());
chatMember.setWorked144(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked144());
;
chatMember.setWorked432(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked432());
;
chatMember.setWorked1240(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked1240());
;
chatMember.setWorked2300(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked2300());
;
chatMember.setWorked3400(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked3400());
;
chatMember.setWorked5600(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked5600());
;
chatMember.setWorked10G(getWorkedDataFromDb.get(chatMember.getCallSign()).isWorked10G());
;
}
/**
*
* This creates the list of the worked stations which had to be displayed in the
* settings menu. TODO: May make this List editable
*
*/
getWorkedDataFromDb.forEach((key, value) -> {
chatController.getLst_DBBasedWkdCallSignList().add(value);
// System.out.println("Key=" + key + ", Value=" + value);
});
// for (Iterator iterator = getWorkedDataFromDb.entrySet().iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
// getLst_DBBasedWkdCallSignList().add(chatMember);
// }
/* Try the not exceptional way to iterate */
// for (ChatMember chatMemberAvl : new ArrayList<ChatMember>(getLst_chatMemberList())) {
// if (getWorkedDataFromDb.containsKey(chatMemberAvl.getCallSign())) {
//
// }
// }
}
}, 10000);
// message = new ChatMessage();
// message.setMessageText("MSG|2|0|/SETNAME " + ownChatMemberObject.getName() + "|0|\r");
// message.setMessageDirectedToServer(true);
// this.getMessageTXBus().add(message);
// message.setMessageText(ownCall.getCallSign());
// this.getMessageTXBus().add(message);
}
public void resetWorkedInfoInGuiLists() {
this.chatController.getLst_chatMemberList().forEach(
chatMember -> chatMember.resetWorkedInformationAtAllBands());
}
/**
* Setting the initial parameters at the chat
*
* @throws InterruptedException
* @throws IOException
*/
public void initialize23000() throws InterruptedException, IOException {
ChatMessage message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText(ownChatMemberObject.getCallSign());
this.getMessageTXBus().add(message);
message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText(password);
this.getMessageTXBus().add(message);
//
message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText(category + "");
this.getMessageTXBus().add(message);
//
message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText("/set qra " + ownChatMemberObject.getQra());
this.getMessageTXBus().add(message);
//
message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText("/set name " + ownChatMemberObject.getName());
this.getMessageTXBus().add(message);
//
message = new ChatMessage();
// message.setDirectedToServer(true);
message.setMessageText("/set here");
this.getMessageTXBus().add(message);
// message = new ChatMessage();
// message.setDirectedToServer(true);
// message.setMessageText("/show user");
// this.getMessageTXBus().add(message);
// will done by another Thread
}
}

View File

@@ -0,0 +1,522 @@
package kst4contest.controller;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import kst4contest.model.ChatMember;
public class DBController {
private static final DBController dbcontroller = new DBController();
private static Connection connection;
// private static final String DB_PATH = System.getProperty("praktiKST.db");
private static final String DB_PATH = ("praktiKST.db");
static {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
System.err.println("Fehler beim Laden des JDBC-Treibers");
e.printStackTrace();
}
}
public DBController() {
initDBConnection();
}
public static DBController getInstance() {
return dbcontroller;
}
/**
* Closes the db connecttion and all statements
*/
public void closeDBConnection() {
try {
this.connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void initDBConnection() {
try {
if (connection != null)
return;
System.out.println("Creating Connection to Database...");
connection = DriverManager.getConnection("jdbc:sqlite:" + DB_PATH);
if (!connection.isClosed())
System.out.println("...Connection established");
} catch (SQLException e) {
throw new RuntimeException(e);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (!connection.isClosed() && connection != null) {
connection.close();
if (connection.isClosed())
System.out.println("Connection to Database closed");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
// private void handleDB() {
// try {
// Statement stmt = connection.createStatement();
// stmt.executeUpdate("DROP TABLE IF EXISTS books;");
// stmt.executeUpdate("CREATE TABLE books (author, title, publication, pages, price);");
// stmt.execute(
// "INSERT INTO books (author, title, publication, pages, price) VALUES ('Paulchen Paule', 'Paul der Penner', "
// + Date.valueOf("2001-05-06") + ", '1234', '5.67')");
//
// PreparedStatement ps = connection.prepareStatement("INSERT INTO books VALUES (?, ?, ?, ?, ?);");
//
// ps.setString(1, "Willi Winzig");
// ps.setString(2, "Willi's Wille");
// ps.setDate(3, Date.valueOf("2011-05-16"));
// ps.setInt(4, 432);
// ps.setDouble(5, 32.95);
// ps.addBatch();
//
// ps.setString(1, "Anton Antonius");
// ps.setString(2, "Anton's Alarm");
// ps.setDate(3, Date.valueOf("2009-10-01"));
// ps.setInt(4, 123);
// ps.setDouble(5, 98.76);
// ps.addBatch();
//
// connection.setAutoCommit(false);
// ps.executeBatch();
// connection.setAutoCommit(true);
//
// ResultSet rs = stmt.executeQuery("SELECT * FROM books;");
// while (rs.next()) {
// System.out.println("Autor = " + rs.getString("author"));
// System.out.println("Titel = " + rs.getString("title"));
// System.out.println("Erscheinungsdatum = " + rs.getDate("publication"));
// System.out.println("Seiten = " + rs.getInt("pages"));
// System.out.println("Preis = " + rs.getDouble("price"));
// }
// rs.close();
// connection.close();
// } catch (SQLException e) {
// System.err.println("Couldn't handle DB-Query");
// e.printStackTrace();
// }
// }
/**************************************************************
*
* Stores a chatmember with its data to the database. <br/>
* <b>It will not insert a callsign entry, if that exists already but update
* locator, name and activity-timer. Callsign is unique and pk!</b> <br/>
* <br/>
* Structure is like following<br/>
*
* "callsign" TEXT NOT NULL UNIQUE,<br/>
* "qra" TEXT,<br/>
* "name" TEXT,<br/>
* "lastActivityDateTime" TEXT,<br/>
* "worked" BOOLEAN,<br/>
* "worked144" BOOLEAN,<br/>
* "worked432" BOOLEAN,<br/>
* "worked1240" BOOLEAN,<br/>
* "worked2300" BOOLEAN,<br/>
* "worked3400" BOOLEAN,<br/>
* "worked5600" BOOLEAN,<br/>
* "worked10G" BOOLEAN,<br/>
*
* @throws SQLException
*/
public void storeChatMember(ChatMember chatMemberToStore) throws SQLException {
try {
Statement stmt = connection.createStatement();
// ResultSet rs = stmt.executeQuery(
// "SELECT * FROM ChatMember where callsign = '" + chatMemberToStore.getCallSign() + "';");
// if (!rs.next()) {
PreparedStatement ps = connection.prepareStatement(
"INSERT OR IGNORE INTO ChatMember VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(callsign) DO UPDATE SET qra = '"
+ chatMemberToStore.getQra() + "', name = '" + chatMemberToStore.getName()
+ "', lastActivityDateTime = '" + chatMemberToStore.getLastActivity()
+ "' where callsign = '" + chatMemberToStore.getCallSign() + "';");
ps.setString(1, chatMemberToStore.getCallSign()); // primary key! Not null!
ps.setString(2, chatMemberToStore.getQra());
ps.setString(3, chatMemberToStore.getName());
ps.setString(4, chatMemberToStore.getLastActivity().toString());
ps.setInt(5, helper_booleanIntConverter(chatMemberToStore.isWorked()));
ps.setInt(6, helper_booleanIntConverter(chatMemberToStore.isWorked144()));
ps.setInt(7, helper_booleanIntConverter(chatMemberToStore.isWorked432()));
ps.setInt(8, helper_booleanIntConverter(chatMemberToStore.isWorked1240()));
ps.setInt(9, helper_booleanIntConverter(chatMemberToStore.isWorked2300()));
ps.setInt(10, helper_booleanIntConverter(chatMemberToStore.isWorked3400()));
ps.setInt(11, helper_booleanIntConverter(chatMemberToStore.isWorked5600()));
ps.setInt(12, helper_booleanIntConverter(chatMemberToStore.isWorked10G()));
ps.addBatch();
connection.setAutoCommit(false);
ps.executeBatch();
connection.setAutoCommit(true);
stmt.close();
// } else {
// System.out.println("DBC: nothing to do");
// Will not store the callsign entry in the database, it exists already
// }
// ResultSet rs = stmt.executeQuery("SELECT * FROM ChatMember;");
// rs.close();
// connection.close();
} catch (SQLException e) {
System.err.println("[DBH, ERROR:] Chatmember could not been stored.");
e.printStackTrace();
connection.close();
}
}
/**************************************************************
*
* This method does a select and build a hashmap of chatmembers whith all worked
* band data, which are stored at the database <br/>
* <b>Usage: one time after startup, for synching the live list with the stored
* list, e.g. after program ended</b> <br/>
* <br/>
* Structure is like following<br/>
*
* "callsign" TEXT NOT NULL UNIQUE,<br/>
* "qra" TEXT,<br/>
* "name" TEXT,<br/>
* "lastActivityDateTime" TEXT,<br/>
* "worked" BOOLEAN,<br/>
* "worked144" BOOLEAN,<br/>
* "worked432" BOOLEAN,<br/>
* "worked1240" BOOLEAN,<br/>
* "worked2300" BOOLEAN,<br/>
* "worked3400" BOOLEAN,<br/>
* "worked5600" BOOLEAN,<br/>
* "worked10G" BOOLEAN,<br/>
*
* @throws SQLException
*/
public HashMap<String, ChatMember> fetchChatMemberWkdDataFromDB() throws SQLException {
HashMap<String, ChatMember> fetchedWorkeddata = new HashMap<>();
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM ChatMember;");
ChatMember updateWkdData;
while (rs.next()) {
updateWkdData = new ChatMember();
updateWkdData.setCallSign(rs.getString("callsign"));
updateWkdData.setWorked(helper_IntToBooleanConverter(rs.getInt("worked")));
updateWkdData.setWorked144(helper_IntToBooleanConverter(rs.getInt("worked144")));
updateWkdData.setWorked432(helper_IntToBooleanConverter(rs.getInt("worked432")));
updateWkdData.setWorked1240(helper_IntToBooleanConverter(rs.getInt("worked1240")));
updateWkdData.setWorked2300(helper_IntToBooleanConverter(rs.getInt("worked2300")));
updateWkdData.setWorked3400(helper_IntToBooleanConverter(rs.getInt("worked3400")));
updateWkdData.setWorked5600(helper_IntToBooleanConverter(rs.getInt("worked5600")));
updateWkdData.setWorked10G(helper_IntToBooleanConverter(rs.getInt("worked10G")));
fetchedWorkeddata.put(updateWkdData.getCallSign(), updateWkdData);
// System.out.println(
// "[DBH, Info:] providing callsign wkd info, wkd, 144, 432, ... : " + updateWkdData.toString());
}
stmt.close();
rs.close();
return fetchedWorkeddata;
// connection.close();
} catch (SQLException e) {
System.err.println("[DBH, ERROR:] Couldn't handle DB-Query");
e.printStackTrace();
connection.close();
}
return fetchedWorkeddata; // TODO: what to do if its empty?
}
/**************************************************************
*
* This method does a select and build a hashmap of chatmembers whith all worked
* band data, which are stored at the database for restore worked state in the
* chat after someone disconnected and reconnected.<br/>
* <b>Usage: MessagebusManagementThread, every time after a new User connects to
* the chat</b> <br/>
* <br/>
*
* @return a modified version of the chatmember-object, which the method takes
*
* @throws SQLException
*/
public ChatMember fetchChatMemberWkdDataForOnlyOneCallsignFromDB(ChatMember checkForThis) {
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt
.executeQuery("SELECT * FROM ChatMember where callsign = '" + checkForThis.getCallSign() + "' ;");
// ChatMember updateWkdData;
// if (!rs.isBeforeFirst()) { //if there are no data to update....
while (rs.next()) {
// updateWkdData = new ChatMember();
// updateWkdData.setCallSign(rs.getString("callsign"));
checkForThis.setWorked(helper_IntToBooleanConverter(rs.getInt("worked")));
checkForThis.setWorked144(helper_IntToBooleanConverter(rs.getInt("worked144")));
checkForThis.setWorked432(helper_IntToBooleanConverter(rs.getInt("worked432")));
checkForThis.setWorked1240(helper_IntToBooleanConverter(rs.getInt("worked1240")));
checkForThis.setWorked2300(helper_IntToBooleanConverter(rs.getInt("worked2300")));
checkForThis.setWorked3400(helper_IntToBooleanConverter(rs.getInt("worked3400")));
checkForThis.setWorked5600(helper_IntToBooleanConverter(rs.getInt("worked5600")));
checkForThis.setWorked10G(helper_IntToBooleanConverter(rs.getInt("worked10G")));
System.out.println(
"[DBH, Info:] providing callsign wkd info, wkd, 144, 432, ... for UA5 new chatmember : "
+ checkForThis.toString());
}
// }
rs.close();
stmt.close();
return checkForThis;
// connection.close();
} catch (SQLException e) {
System.err.println("[DBH, ERROR:] Couldn't handle DB-Query");
e.printStackTrace();
try {
connection.close();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return checkForThis; // TODO: what to do if its empty?
}
/**************************************************************
*
* This method removes all worked band data for each callsign in the
* database.<br/>
* <b>Usage: User triggered after User clicked the reset-wkd button, may in each
* new contest period</b> <br/>
* <br/>
*
* @return true if reset was successful
*
* @throws SQLException
*/
public int resetWorkedDataInDB() {
try {
Statement stmt = connection.createStatement();
int affected = stmt.executeUpdate("update ChatMember set worked = 0, worked144 = 0, worked432 = 0, worked1240 = 0, worked2300 = 0, worked3400 = 0, worked5600 = 0, worked10G = 0;");
stmt.close();
return affected;
} catch (SQLException e) {
System.err.println("[DBH, ERROR:] Couldn't reset the worked data");
e.printStackTrace();
try {
connection.close();
} catch (SQLException e1) {
e1.printStackTrace();
return -1;
}
return -1;
}
// return checkForThis; // TODO: what to do if its empty?
}
/**************************************************************
*
* Updates the worked-information for a chatmember at the db <br/>
* <b>It will not revert wkd info, only add wkd info for a band (only new worked
* bands will be stored, no worked info will be removed).</b><br/>
* The wkd fields should be cleaned by the user at the begin of a new
* contest<br/>
*
* // This will update the worked info on a worked chatmember. The DBHandler
* will check, if an entry at the db had been modified. If not, then the worked
* station had not been stored yet and have to be stored. The informations have
* to be stored, then by calling the store method of the DBHandler (<b>it´s up
* to you, guy!</b>)!<br/>
* <br/>
*
* @return true if an entry had been modified, false if not
*
*
* <br/>
* <br/>
* Structure is like following<br/>
*
* "callsign" TEXT NOT NULL UNIQUE,<br/>
* "qra" TEXT,<br/>
* "name" TEXT,<br/>
* "lastActivityDateTime" TEXT,<br/>
* "worked" BOOLEAN,<br/>
* "worked144" BOOLEAN,<br/>
* "worked432" BOOLEAN,<br/>
* "worked1240" BOOLEAN,<br/>
* "worked2300" BOOLEAN,<br/>
* "worked3400" BOOLEAN,<br/>
* "worked5600" BOOLEAN,<br/>
* "worked10G" BOOLEAN,<br/>
*
* @throws SQLException
*/
public boolean updateWkdInfoOnChatMember(ChatMember chatMemberToStore) throws SQLException {
try {
Statement stmt = connection.createStatement();
// stmt.close();
/**
* at first, mark the station as worked, always
*/
PreparedStatement ps = connection.prepareStatement("UPDATE ChatMember set worked = ? WHERE CallSign = ?");
ps.setInt(1, 1); // 1st variable will be set
ps.setString(2, chatMemberToStore.getCallSign());
ps.addBatch();
connection.setAutoCommit(false);
ps.executeBatch();
connection.setAutoCommit(true);
/**
* Then, handle the update information of received worked udp message
*/
String bandVariable = "worked";
if (chatMemberToStore.isWorked144()) {
bandVariable = "worked144";
} else if (chatMemberToStore.isWorked432()) {
bandVariable = "worked432";
} else if (chatMemberToStore.isWorked1240()) {
bandVariable = "worked1240";
} else if (chatMemberToStore.isWorked2300()) {
bandVariable = "worked2300";
} else if (chatMemberToStore.isWorked3400()) {
bandVariable = "worked3400";
} else if (chatMemberToStore.isWorked5600()) {
bandVariable = "worked5600";
} else if (chatMemberToStore.isWorked10G()) {
bandVariable = "worked10G";
} else {
System.out.println("[DBCtrl, Error]: unknown at which band the qso had been!");
}
PreparedStatement ps2 = connection
.prepareStatement("UPDATE ChatMember set " + bandVariable + " = ? WHERE CallSign = ?");
ps2.setInt(1, 1); // 1st variable will be set
ps2.setString(2, chatMemberToStore.getCallSign());
ps2.addBatch();
connection.setAutoCommit(false);
ps2.executeBatch();
connection.setAutoCommit(true);
stmt.close();
System.out.println("updated count of cols: " + ps2.getUpdateCount());
if (ps2.getUpdateCount() != 0) {
return true;
} else
return false; // no entry to update: user had not been stored at a chatmember in table
// } else {
// System.out.println("DBC: nothing to do");
// Will not store the callsign entry in the database, it exists already
// }
// ResultSet rs = stmt.executeQuery("SELECT * FROM ChatMember;");
// rs.close();
// connection.close();
} catch (SQLException e) {
System.err.println("[DBH, ERROR:] Couldn't handle DB-Query");
e.printStackTrace();
connection.close();
return false;
}
}
private int helper_booleanIntConverter(boolean convertToInt) {
if (convertToInt) {
return 1;
} else
return 0;
}
private boolean helper_IntToBooleanConverter(int valueFromDBField) {
if (valueFromDBField != 0) {
return true;
} else
return false;
}
public static void main(String[] args) throws SQLException {
DBController dbc = DBController.getInstance();
// dbc.initDBConnection();
ChatMember dummy = new ChatMember();
dummy.setCallSign("DM5M");
dummy.setQra("jo51ij");
dummy.setName("Team Test");
dummy.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat());
dummy.setWorked5600(true);
// dummy.setWorked432(true);
// dbc.storeChatMember(dummy);
dbc.updateWkdInfoOnChatMember(dummy);
// dbc.handleDB();
}
}

View File

@@ -0,0 +1,63 @@
package kst4contest.controller;
import java.io.*;
import java.net.*;
import kst4contest.model.ChatMessage;
/**
* Consolereader, reads a full line and adds it to the tx-queue after formatting it like: <br> <br>
*
* MSG|2|0|/cq DO5AMF kst4contest.test|0| <br/><br/>
*
* No need for it as it´s not longer a console application
*/
public class InputReaderThread extends Thread {
private PrintWriter writer;
private Socket socket;
private ChatController client;
public InputReaderThread(ChatController client) throws InterruptedException {
this.client = client;
}
public void run() {
while (true) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
ChatMessage ownMSG = new ChatMessage();
// ownMSG.setDirectedToServer(true);
String sendThisMessage23001 = "";
try {
sendThisMessage23001 = reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ownMSG.setMessageText("MSG|" + this.client.getCategory().getCategoryNumber() + "|0|" + sendThisMessage23001 + "|0|");
// System.out.println("inreader " + ownMSG.getMessage() + client.getMessageTXBus().size());
// client.getMessageTXBus().add(ownMSG);
client.getMessageTXBus().add(ownMSG);
try {
this.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
package kst4contest.controller;
import java.io.*;
import java.net.*;
import kst4contest.model.ChatMessage;
/**
* This thread is responsible for reading telnet servers input at port 23001 and printing it
* to the console.
* It runs in an infinite loop until the client disconnects from the server.
*
* @author www.codejava.net
*/
public class ReadThread extends Thread {
private BufferedReader reader;
private Socket socket;
private ChatController client;
public boolean accidentalDisconnected;
public boolean isAccidentalDisconnected() {
return accidentalDisconnected;
}
public void setAccidentalDisconnected(boolean accidentalDisconnected) {
this.accidentalDisconnected = accidentalDisconnected;
}
// private boolean readingFinished = true; //kst4contest.test 4 23001
private boolean readingFinished = true;
InputStream input;
public ReadThread(Socket socket, ChatController client) {
this.socket = socket;
this.client = client;
try {
input = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(input));
} catch (IOException ex) {
System.out.println("Error getting input stream: " + ex.getMessage());
ex.printStackTrace();
}
}
public void run() {
Thread.currentThread().setName("ReadFromTelnetThread");
ChatMessage message; //bugfix leak, moved out of while
while (true) {
// System.out.println("rdth");
try {
String response = reader.readLine();
message = new ChatMessage();
message.setMessageText(response);
// message.setDirectedToServer(false);
// message.setDirectedToServer(false);
// message.setDirectedToServer(false);
if (response != null) {
client.getMessageRXBus().put(message);
// System.out.println("[RT]: read message and added it to msgrxqueue --- " + response + " ---");
} else {
System.out.println("[RT]: read message responsed a nullstring, do nothing, buffersize = " + socket.getReceiveBufferSize() + ", reader ready? "
+ reader.ready());
// reader = new BufferedReader(new InputStreamReader(input));
// response = reader.readLine();
this.client.getSocket().close();
this.interrupt();
}
}
catch (Exception sexc) {
System.out.println("[ReadThread, CRITICAL: ] Socket geschlossen: " + sexc.getMessage());
try {
this.client.getSocket().close();
this.interrupt();
break;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// try {
// sleep(3000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// try {
// System.out.println("RDTH: try new socket");
// this.client.getSocket().close();
// this.client.getSocket().close();
// this.client.setSocket(new Socket(this.client.getHostname(), this.client.getPort()));
// socket.connect(new InetSocketAddress(this.client.getHostname(), this.client.getPort()));
// System.out.println("[Readthread, Warning:] new socket connected? -> " + socket.isConnected());
// input = socket.getInputStream();
// reader = new BufferedReader(new InputStreamReader(input));
//
// this.sleep(5000);
// } catch (IOException | InterruptedException e2) {
// // TODO Auto-generated catch block
// System.out.println("fucktah");
// e2.printStackTrace();
// }
// try {
// sleep(2000);
// } catch (InterruptedException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
// try {
// this.client.getSocket().close();
// this.client.setSocket(new Socket(this.client.getHostname(), this.client.getPort()));
// } catch (UnknownHostException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}
}
public boolean terminateConnection() throws IOException {
this.reader.close();
this.input.close();
this.socket.close();
return true;
}
public boolean isReadingFinished() {
return readingFinished;
}
public void setReadingFinished(boolean readingReady) {
this.readingFinished = readingReady;
}
}

View File

@@ -0,0 +1,270 @@
package kst4contest.controller;
import java.io.*;
import java.net.*;
import java.util.Comparator;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import kst4contest.model.AirPlane;
import kst4contest.model.AirPlaneReflectionInfo;
import kst4contest.model.ChatMember;
/**
* This thread is responsible for reading server's input and printing it to the
* console. It runs in an infinite loop until the client disconnects from the
* server.
*
* @author www.codejava.net
*/
public class ReadUDPbyAirScoutMessageThread extends Thread {
private BufferedReader reader;
private Socket socket;
private ChatController client;
private int localPort;
private String ASIdentificator, ChatClientIdentificator;
public ReadUDPbyAirScoutMessageThread(int localPort) {
this.localPort = localPort;
}
public ReadUDPbyAirScoutMessageThread(int localPort, ChatController client, String ASIdentificator,
String ChatClientIdentificator) {
this.localPort = localPort;
this.client = client;
this.ASIdentificator = ASIdentificator;
this.ChatClientIdentificator = ChatClientIdentificator;
}
@Override
public void interrupt() {
super.interrupt();
try {
if (this.socket != null) {
this.socket.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
Thread.currentThread().setName("ReadUDPByAirScoutThread");
DatagramSocket socket = null;
boolean running;
byte[] buf = new byte[1777];
DatagramPacket packet;
// DatagramPacket packet = new DatagramPacket(buf, buf.length); //changed due to save memory
packet = new DatagramPacket(buf, buf.length);
try {
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(localPort));
socket.receive(packet);
socket.setSoTimeout(3000);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
}
while (true) {
// packet = new DatagramPacket(buf, buf.length);
// DatagramPacket packet = new DatagramPacket(SRPDefinitions.BYTE_BUFFER_MAX_LENGTH);
try {
if (this.client.isDisconnectionPerformedByUser()) {
break;//TODO: what if it´s not the finally closage but a band channel change?
}
socket.receive(packet);
} catch (SocketTimeoutException e2) {
// this will catch the repeating Sockettimeoutexception...nothing to do
// e2.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InetAddress address = packet.getAddress();
int port = packet.getPort();
// packet = new DatagramPacket(buf, buf.length, address, port);
String received = new String(packet.getData(), packet.getOffset(), packet.getLength());
received = received.trim();
if (received.contains("ASSETPATH") || received.contains("ASWATCHLIST")) {
// do nothing, that is your own message
} else if (received.contains("ASNEAREST:")) {
processASUDPMessage(received);
// System.out.println("[ReadUSPASTh, info:] received AS String " + received);
AirPlaneReflectionInfo apReflectInfoForChatMember;
apReflectInfoForChatMember = processASUDPMessage(received);
if (this.client.getLst_chatMemberList().size() != 0) {
try {
// if (this.client.checkListForChatMemberIndexByCallSign(apReflectInfoForChatMember.getReceiver()) != -1) {
this.client.getLst_chatMemberList()
.get(this.client.checkListForChatMemberIndexByCallSign(
apReflectInfoForChatMember.getReceiver()))
.setAirPlaneReflectInfo(apReflectInfoForChatMember); // TODO: here we set the ap info at
// the central instance of
// chatmember list .... -1 is a
// problem!
/**
* CK| MSGBUS BGFX Listactualizer Exception in thread "Thread-10"
* java.util.ConcurrentModificationException at
* java.base/java.util.AbstractList$Itr.checkForComodification(AbstractList.java:399)
* at java.base/java.util.AbstractList$Itr.next(AbstractList.java:368) at
* kst4contest.controller.ChatController.checkListForChatMemberIndexByCallSign(ChatController.java:173)
* at
* kst4contest.controller.ReadUDPbyAirScoutMessageThread.run(ReadUDPbyAirScoutMessageThread.java:93)
*
*/
// }
} catch (Exception e) {
System.out.println("ReadUdpByAsMsgTh, Warning:"
+ apReflectInfoForChatMember.getReceiver().getCallSign()
+ " is not in the Chatmemberlist or the Chatmemberlist is modified by another Thread");
// TODO: handle exception
}
}
}
// packet = null; //reset packet
buf = new byte[1777]; // reset buffer for future smaller packets
}
}
public AirPlaneReflectionInfo processASUDPMessage(String udpStringToProcess) {
// System.out.println("RDUDPAS RECV: " + udpStringToProcess);
// TODO: filter messages which are directed to another client
/*
* Example mesage: ASNEAREST: "AS" "KST"
* "2023-04-01 21:33:42Z,DO5AMF,JN49GL,G4CLA,IO92JL,9,VLG2PT,M,190,75,14,BAW809,M,250,50,18,BEL6CM,M,143,50,12,WZZ6719,M,148,50,11,KLM1678,M,313,75,22,TRA1B,M,271,75,20,SAS4728,M,125,75,9,RYR6TL,M,90,75,6,UAE10,S,96,50,6"
* Syntax: ASNEAREST: "AS" "KST" "2023-03-09
* 23:21:50Z,DO5AMF,JN49GL,DM5M,JO51IJ,3, SWT8TB,M,121,75,16, ^kleines Ding
* ^^^Distanz km ^^Potenzial 0-100% ^^Dauer bis ankunft minutes
*/
String[] fullStringSplitter;
String[] apStringSplitter;
AirPlaneReflectionInfo apInfo = new AirPlaneReflectionInfo();
ObservableList<AirPlane> airplaneList = FXCollections.observableArrayList();
if (udpStringToProcess.contains("ASNEAREST: ")) {
udpStringToProcess = udpStringToProcess.replace("ASNEAREST: ", "");
udpStringToProcess = udpStringToProcess.replace(" ", "");
fullStringSplitter = udpStringToProcess.split("\"");
// for (int i = 0; i < fullStringSplitter.length; i++) {
// System.out.println(i + " " + fullStringSplitter[i]);
// }
String APInfoString = fullStringSplitter[5];
apStringSplitter = APInfoString.split(",");
String[] allAPInfos = new String[apStringSplitter.length - 6]; // new String shold only provide aps, nothing
// other
for (int i = 0; i < apStringSplitter.length; i++) {
if (i >= 6) {
allAPInfos[i - 6] = apStringSplitter[i];
}
// System.out.println(i + ": " + apStringSplitter[i]);
// if (i>=6) {
// allAPInfos[i-6] = apStringSplitter[i];
// System.out.println(i-5 + " > " + apStringSplitter[i]);
//
//
//
// }
}
AirPlane airPlane = new AirPlane();
for (int i = 0; i < allAPInfos.length; i++) {
if (((i) % 5) == 0) {
airPlane = new AirPlane();
// airPlane = new AirPlane();
airPlane.setApCallSign(allAPInfos[i]);
// System.out.println(i + " AP: " + allAPInfos[i]);
} else if (((i) % 5) == 1) {
airPlane.setApSizeCategory(allAPInfos[i]);
// System.out.println(i + " cat: " + allAPInfos[i]);
} else if (((i) % 5) == 2) {
airPlane.setDistanceKm(Integer.parseInt(allAPInfos[i]));
// System.out.println(i + " dist: " + allAPInfos[i]);
} else if (((i) % 5) == 3) {
airPlane.setPotential(Integer.parseInt(allAPInfos[i]));
// System.out.println(i + " potential: " + allAPInfos[i]);
}
if (((i) % 5) == 4) {
// System.out.println(i + " duration: " + allAPInfos[i]);
airPlane.setArrivingDurationMinutes(Integer.parseInt(allAPInfos[i]));
airplaneList.add(airPlane);
}
}
apInfo.setDate(apStringSplitter[0]);
ChatMember apStartCallSign = new ChatMember();
apStartCallSign.setCallSign(apStringSplitter[1]);
apStartCallSign.setQra(apStringSplitter[2]);
apInfo.setSender(apStartCallSign); // usally its the callsign of own chatmember object, may check this
ChatMember apDestCallSign = new ChatMember();
apDestCallSign.setCallSign(apStringSplitter[3]);
apDestCallSign.setQra(apStringSplitter[4]);
apInfo.setReceiver(apDestCallSign);
apInfo.setAirPlanesReachableCntr(Integer.parseInt(apStringSplitter[5]));
apInfo.setRisingAirplanes(airplaneList);
// System.out.println("total airplanes for rx stn " + apInfo.getReceiver().getCallSign() + ": " + airplaneList.size() + " " + apInfo.toString());
airplaneList.sort(Comparator.comparing(AirPlane::getPotential).reversed()
.thenComparing(AirPlane::getArrivingDurationMinutes));
}
return apInfo;
}
public boolean terminateConnection() throws IOException {
this.socket.close();
return true;
}
}

View File

@@ -0,0 +1,406 @@
package kst4contest.controller;
import java.io.*;
import java.net.*;
import java.sql.SQLException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import kst4contest.model.ChatMember;
/**
* This thread is responsible for reading server's input and printing it to the
* console. It runs in an infinite loop until the client disconnects from the
* server.
*
* @author www.codejava.net
*/
public class ReadUDPbyUCXMessageThread extends Thread {
private BufferedReader reader;
private Socket socket;
private ChatController client;
public ReadUDPbyUCXMessageThread(int localPort) {
}
public ReadUDPbyUCXMessageThread(int localPort, ChatController client) {
this.client = client;
}
@Override
public void interrupt() {
super.interrupt();
try {
if (this.socket != null) {
this.socket.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
Thread.currentThread().setName("ReadUDPByUCXLogThread");
DatagramSocket socket = null;
boolean running;
byte[] buf = new byte[1777];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
socket = new DatagramSocket(12060);
socket.setSoTimeout(11000); //TODO try for end properly
}
catch (SocketException e) {
//this will catch the repeating Sockettimeoutexception...nothing to do
// e.printStackTrace();
}
while (true) {
boolean timeOutIndicator = false;
if (this.client.isDisconnectionPerformedByUser()) {
break;//TODO: what if it´s not the finally closage but a band channel change?
}
// packet = new DatagramPacket(buf, buf.length); //TODO: Changed that due to memory leak, check if all works (seems like that)
// DatagramPacket packet = new DatagramPacket(SRPDefinitions.BYTE_BUFFER_MAX_LENGTH); //TODO: Changed that due to memory leak, check if all works (seems like that)
try {
socket.receive(packet);
} catch (SocketTimeoutException e2) {
timeOutIndicator = true;
// this will catch the repeating Sockettimeoutexception...nothing to do
// e2.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InetAddress address = packet.getAddress();
int port = packet.getPort();
// packet = new DatagramPacket(buf, buf.length, address, port);
String received = new String(packet.getData(), packet.getOffset(), packet.getLength());
received = received.trim();
// System.out.println("recvudpucx");
if (!timeOutIndicator) {
processUCXUDPMessage(received);
} else {
//dont process the empty message
}
buf = new byte[1777]; // reset buffer for future smaller packets
}
}
public String processUCXUDPMessage(String udpPacketToProcess) {
File logUDPMessageToThisFile;
String udpMsg = udpPacketToProcess;
ChatMember modifyThat = null;
// System.out.println(udpMsg);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (ParserConfigurationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(udpMsg)));
/**
* case Log-QSO-Packet in ucxlog
*
*/
NodeList list = doc.getElementsByTagName("contactinfo");
if (list.getLength() != 0) {
for (int temp = 0; temp < list.getLength(); temp++) {
Node node = list.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String call = element.getElementsByTagName("call").item(0).getTextContent();
// call = call.toLowerCase();
String band = element.getElementsByTagName("band").item(0).getTextContent();
System.out.println("[Readudp, info ]: received Current Element :" + node.getNodeName()
+ "call: " + call + " / " + band);
ChatMember workedCall = new ChatMember();
workedCall.setCallSign(call);
workedCall.setWorked(true);
switch (band) {
case "144": {
workedCall.setWorked144(true);
break;
}
case "432": {
workedCall.setWorked432(true);
break;
}
case "1240": {
workedCall.setWorked1240(true);
break;
}
case "2300": {
workedCall.setWorked2300(true);
break;
}
case "3400": {
workedCall.setWorked3400(true);
break;
}
case "5600": {
workedCall.setWorked5600(true);
break;
}
case "10G": {
workedCall.setWorked10G(true);
}
default:
System.out.println("[ReadUDPFromUCX, Error:] unexpected band value: \"" + band + "\"");
break;
}
// if (!client.getMap_ucxLogInfoWorkedCalls().containsKey("call")) {
// client.getMap_ucxLogInfoWorkedCalls().put(call, workedCall);
// } else
{
/**
* That means, the station is worked already but maybe at another band. So we
* have to get the worked ChatMember out of the list and to modify the worked
* options.
*/
// modifyThat = (ChatMember) client.getMap_ucxLogInfoWorkedCalls().get(call);
int indexOfChatMemberInTable = -1;
indexOfChatMemberInTable = client.checkListForChatMemberIndexByCallSign(workedCall);
if (indexOfChatMemberInTable == -1) {
// do nothing
} else {
modifyThat = client.getLst_chatMemberList().get(indexOfChatMemberInTable);
// modifyThat.setWorked(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat)).setWorked(true);
if (workedCall.isWorked144()) {
modifyThat.setWorked144(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked144(true);
} else if (workedCall.isWorked432()) {
modifyThat.setWorked432(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked432(true);
} else if (workedCall.isWorked1240()) {
modifyThat.setWorked1240(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked1240(true);
} else if (workedCall.isWorked2300()) {
modifyThat.setWorked2300(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked2300(true);
} else if (workedCall.isWorked3400()) {
modifyThat.setWorked3400(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked3400(true);
} else if (workedCall.isWorked5600()) {
modifyThat.setWorked5600(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked5600(true);
} else if (workedCall.isWorked10G()) {
modifyThat.setWorked10G(true);
client.getLst_chatMemberList()
.get(client.checkListForChatMemberIndexByCallSign(modifyThat))
.setWorked10G(true);
}
}
}
boolean isInChat = this.client.getDbHandler().updateWkdInfoOnChatMember(workedCall);
// This will update the worked info on a worked chatmember. DBHandler will
// check, if an entry at the db had been modified. If not, then the worked
// station had not been stored. DBHandler will store the informations then.
if (!isInChat) {
workedCall.setName("unknown");
workedCall.setQra("unknown");
workedCall.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat());
this.client.getDbHandler().storeChatMember(workedCall);
}
logUDPMessageToThisFile = new File(this.client.getChatPreferences()
.getLogSynch_storeWorkedCallSignsFileNameUDPMessageBackup());
FileWriter fileWriterPersistUDPToFile = null;
BufferedWriter bufwrtrRawMSGOut;
try {
fileWriterPersistUDPToFile = new FileWriter(logUDPMessageToThisFile, true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
bufwrtrRawMSGOut = new BufferedWriter(fileWriterPersistUDPToFile);
if (modifyThat != null) {
bufwrtrRawMSGOut.write("\n" + modifyThat.toString());
bufwrtrRawMSGOut.flush();
bufwrtrRawMSGOut.close();
} else {
bufwrtrRawMSGOut.write("\n" + workedCall.toString());
bufwrtrRawMSGOut.flush();
bufwrtrRawMSGOut.close();
}
}
}
} else {
list = doc.getElementsByTagName("RadioInfo");
for (int temp = 0; temp < list.getLength(); temp++) {
Node node = list.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String formattedQRG;
Element element = (Element) node;
String qrg = element.getElementsByTagName("Freq").item(0).getTextContent();
String mode = element.getElementsByTagName("Mode").item(0).getTextContent();
// System.out.println("QRG Length: " + qrg.length() + " // " + qrg);
/**
* The following if statement is only for formatting the frequency input for
* good readability to avoid values like 129601000 and set it to something
* readable like 1296.010.00
*
*/
if (qrg.length() == 6) {
// 701000 KHz
formattedQRG = qrg.format("%s.%s.%s", qrg.substring(0, 1), qrg.substring(2, 5),
qrg.substring(5, 6));
} else if (qrg.length() == 7) {
// 700000 KHz
formattedQRG = qrg.format("%s.%s.%s", qrg.substring(0, 2), qrg.substring(2, 5),
qrg.substring(5, 7));
} else if (qrg.length() == 8) {
// 144.123.22 KHz
formattedQRG = qrg.format("%s.%s.%s", qrg.substring(0, 3), qrg.substring(3, 6),
qrg.substring(6, 8));
} else if (qrg.length() == 9) {
// 1296.010.00
formattedQRG = qrg.format("%s.%s.%s", qrg.substring(0, 4), qrg.substring(4, 7),
qrg.substring(7, 9));
} else if (qrg.length() == 10) {
// 10000.010.00
formattedQRG = qrg.format("%s.%s.%s", qrg.substring(0, 5), qrg.substring(5, 8),
qrg.substring(8, 10));
}
else {
formattedQRG = qrg;
}
// System.out.println("Current Element :" + node.getNodeName());
// System.out.println("Radio QRG : " + qrg);
// System.out.println("Radio Mode: " + mode);
// System.out.println("[ReadUDPFromUCX, Info:] Setted QRG pref to: \"" + qrg + "\"" );
this.client.getChatPreferences().getMYQRG().set(formattedQRG);
System.out.println("[ReadUDPbyUCXTh: ] Radioinfo processed: " + formattedQRG);
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
System.out.println(e.getCause());
System.out.println(e.getMessage());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println("[ReadUDPbyUCXTh: ] worked size = " + this.client.getMap_ucxLogInfoWorkedCalls().size());
// System.out.println("[ReadUDPbyUCXTh: ] worked size = removeThisActions" );
return "";
}
public boolean terminateConnection() throws IOException {
this.socket.close();
return true;
}
}

View File

@@ -0,0 +1,86 @@
package kst4contest.controller;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import kst4contest.model.ChatMember;
public class RegexTester {
public static void main(String[] args) {
String temp;
temp = "DL1KDA JO30EP Alex\r\n"
+ "DL3LST JO61FI Ray(Rainer)\r\n"
+ "DL4ZAQ JN49MP Peter 2m&70cm&6m\r\n"
+ "DL9LBH JN59ID Hans 2/70/23\r\n"
+ "DO5AMF JN49FK Marc\r\n"
+ "F5ICN JN03BF Alex QRV 2/70/23\r\n"
+ "F6GRA JN04DB Carol 2m\r\n"
+ "F6HTJ JN12KQ Michel\r\n"
+ "G0BIX JO01GI Terry\r\n"
+ "G0HOF IO92UL Ken 11el + 400 W\r\n"
+ "G0LBK JO03BD David\r\n"
+ "G0MBL JO01QH Andrew 2m\r\n"
+ "G1SDX IO80FL Grant\r\n"
+ "G3MXH JO02LF Terry\r\n"
+ "G3OVH IO92JP Tony\r\n"
+ "G3VCA IO93MG bob\r\n"
+ "G4AEP IO91MB bill\r\n"
+ "G4DHF IO92UU David\r\n"
+ "G4FUF JO01GN Keith\r\n"
+ "G4TRA IO81WN Steve\r\n"
+ "G6HKS IO92OB Richard\r\n"
+ "G8SEI IO92FO Jeff 6/4/2/70\r\n"
+ "GM0EWX IO67UL Calum\r\n"
+ "GW8IZR IO73TI Paul\r\n"
+ "IV3GTH JN65RU Gigi\r\n"
+ "IZ2XZM JN45KH Nick\r\n"
+ "LY1BWB KO24PR VU Club 2/70\r\n"
+ "LY2EN KO24PQ QRT\r\n"
+ "OK1FPR JO80CE Milos\r\n"
+ "OV3T JO46CM Thomas\r\n"
+ "OY4TN IP62NB Trygvi 11EL/350W\r\n"
+ "OZ2M JO65FR Bo PNGonVHF\r\n"
+ "OZ3Z JO45UN Anders @432.228\r\n"
+ "OZ7UV JO65DH Svend\r\n"
+ "PA3DOL JO22MT Sjoerd\r\n"
+ "PA3PCV JO20VV Marcel 2m\r\n"
+ "PA9R JO22JK Rob\r\n"
+ "S52FO JN76EF Janez\r\n"
+ "S53RM JN76HD Sine\r\n"
+ "SM2CEW KP15CR Peter\r\n"
+ "SP6VGJ JO81HU Jacek";
Pattern pattern = Pattern.compile("([a-zA-Z0-9]{2}/{1})?([a-zA-Z0-9]{1,3}[0-9][a-zA-Z0-9]{0,3}[a-zA-Z]{0,3})(/p)? [a-zA-Z]{2}[0-9]{2}[a-zA-Z]{2} [ -~]{1,20}");
Matcher matcher = pattern.matcher(temp);
/**
* "([a-zA-Z0-9]{1,2}\/)?[a-zA-Z0-9]{1,3}[0-9][a-zA-Z0-9]{0,3}[a-zA-Z](\/(p|m))?( )[a-zA-Z]{2}[0-9]{2}[a-zA-Z]{2}[ -~]{0,30}"gm
* Thats a line of the show users list
*/
while (matcher.find()) {
// System.out.println("Chatmember detected: "+ matcher.group() + " " + matcher.start());
ChatMember member = new ChatMember();
String matchedString = matcher.group();
String[] splittedUserString;
splittedUserString = matchedString.split(" ");
member.setCallSign(splittedUserString[0]);
member.setQra(splittedUserString[1]);
String stringAggregation = "";
for (int i = 2; i < splittedUserString.length; i++) {
stringAggregation += splittedUserString[i] + " ";
}
member.setName(stringAggregation);
System.out.println("Call: " + member.getCallSign() + ", QRA: " + member.getQra() + ", Name: " + member.getName());
}
}
}

View File

@@ -0,0 +1,28 @@
/**
*
*/
package kst4contest.controller;
import java.io.IOException;
/**
* @author mywire
*
*/
public class StartChat {
/**
* @param args
* @throws InterruptedException
* @throws IOException
*/
public static void main(String[] args) throws InterruptedException, IOException {
System.out.println("[Startchat:] Starting new Chat instance");
ChatController client = new ChatController();
client.execute();
}
}

View File

@@ -0,0 +1,83 @@
package kst4contest.controller;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import kst4contest.model.ChatMember;
public class UCXLogFileToHashsetParser {
public BufferedReader fileReader;
private final String PTRN_CallSign = "(([a-zA-Z]{1,2}[\\d{1}]?\\/)?(\\d{1}[a-zA-Z][\\d{1}][a-zA-Z]{1,3})((\\/p)|(\\/\\d))?)|(([a-zA-Z0-9]{1,2}[\\d{1}]?\\/)?(([a-zA-Z]{1,2}(\\d{1}[a-zA-Z]{1,4})))((\\/p)|(\\/\\d))?)";
public UCXLogFileToHashsetParser(String filePathAndName) {
try {
fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePathAndName))));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* check if a line of the ucxlog-Logfile inhibits a Callsign<br/>
* <b>returns ChatMember = null, if no frequency found</b>
*
* @param chatMessage
*/
private ChatMember checkIfLineInhibitsCallSign(String line) {
Pattern pattern = Pattern.compile(PTRN_CallSign); // TODO: PTRN should depend to category-selection of own stn
Matcher matcher = pattern.matcher(line);
String matchedString = "";
while (matcher.find()) {
matchedString = matcher.group();
// System.out.println("[UCXLogFile:] Processed worked Callsign from file: " + matchedString);
}
ChatMember newChatMember = new ChatMember();
newChatMember.setCallSign(matchedString.toUpperCase());
return newChatMember;
}
/**
* Parses an ucxlog-live-file (full qualified path given by constructor
* argument), looks by regex for callsigns and builds a hashmap with only one
* entry by callsign
*/
public HashMap<String, String> parse() throws IOException {
HashMap<String, String> chatMemberMap = new HashMap();
String line;
while ((line = fileReader.readLine()) != null) {
// System.out.println("raw: " + line);
ChatMember temp = checkIfLineInhibitsCallSign(line);
if (temp.getCallSign() != "") {
chatMemberMap.put(temp.getCallSign(), temp.getCallSign());
}
}
// System.out.println(chatMemberMap.size());
return chatMemberMap;
}
}

View File

@@ -0,0 +1,326 @@
package kst4contest.controller;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TimerTask;
import javafx.collections.ObservableList;
import kst4contest.model.ChatMember;
import kst4contest.model.ClusterMessage;
public class UserActualizationTask extends TimerTask {
private ChatController client;
public UserActualizationTask(ChatController client) {
this.client = client;
}
@Override
public void run() {
Thread.currentThread().setName("UserActualizationTask");
// System.out.println("[Useract: ] Thread runned now");
// System.out.println("***********************Useract started");
/**
* ******************************************since here: old mechanic for
* marking worked stations by .ucx-file
*/
HashMap<String, String> fetchedWorkedSet = new HashMap<>();
// HashMap<String, String> fetchedWorkedSetUdpBckup = new HashMap<>();
File f = new File(this.client.getChatPreferences().getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly());
if (!f.exists() && !f.isDirectory()) {
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
UCXLogFileToHashsetParser getWorkedCallsignsOfUCXLogFile = new UCXLogFileToHashsetParser(
this.client.getChatPreferences().getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly());
// UCXLogFileToHashsetParser getWorkedCallsignsOfUDPBackupFile = new UCXLogFileToHashsetParser(
// this.client.getChatPreferences().getLogSynch_storeWorkedCallSignsFileNameUDPMessageBackup());
try {
fetchedWorkedSet = getWorkedCallsignsOfUCXLogFile.parse();
// fetchedWorkedSetUdpBckup = getWorkedCallsignsOfUDPBackupFile.parse();
// for (HashMap.Entry entry : fetchedWorkedSet.entrySet()) {
// String key = (String) entry.getKey();
// Object value = entry.getValue();
// System.out.println("key " + key);
// }
System.out.println("USERACT: fetchedWorkedSet size: " + fetchedWorkedSet.size());
// System.out.println("USERACT: fetchedWorkedSetudpbckup size: " + fetchedWorkedSetUdpBckup.size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ObservableList<ChatMember> praktiKSTActiveUserList = this.client.getLst_chatMemberList();
for (Iterator iterator = praktiKSTActiveUserList.iterator(); iterator.hasNext();) {
ChatMember chatMember = (ChatMember) iterator.next();
// System.out.println(chatMember.getCallSign());
// System.out.println("USERACT active user list entries " + praktiKSTActiveUserList.size());
if (fetchedWorkedSet.containsKey(chatMember.getCallSign())) {
chatMember.setWorked(true);
System.out.println("[USERACT, info:] marking Chatuser " + chatMember.getCallSign()
+ " as worked, based on READONLY-Logfile.");
}
// if (fetchedWorkedSetUdpBckup.containsKey(chatMember.getCallSign())) {
// chatMember.setWorked(true);
// System.out.println("[USERACT, info:] marking Chatuser " + chatMember.getCallSign() + " as worked, based on UDPLsnBackup-Logfile.");
// }
}
ObservableList<ClusterMessage> praktiKSTClusterList = this.client.getLst_clusterMemberList();
for (Iterator iterator = praktiKSTClusterList.iterator(); iterator.hasNext();) {
ClusterMessage clusterMessage = (ClusterMessage) iterator.next();
if (fetchedWorkedSet.containsKey(clusterMessage.getReceiver().getCallSign())) {
clusterMessage.setReceiverWkd(true);
System.out.println("[USERACT, info:] marking Clusterspotted "
+ clusterMessage.getReceiver().getCallSign() + " as worked.");
}
// if (fetchedWorkedSetUdpBckup.containsKey(clusterMessage.getReceiver().getCallSign())) {
// clusterMessage.setReceiverWkd(true);
// System.out.println("[USERACT, info:] marking Clusterspotted "
// + clusterMessage.getReceiver().getCallSign() + " as worked.");
// }
}
/**
* ******************************************end here: old mechanic for marking
* worked stations by .ucx-file
*
*/
/**
* ******************************************since here: new mechanic for
* marking worked stations by udp/adif based information
*/
// HashMap<String, String> fetchedWorkedMap = new HashMap<>();
//
// fetchedWorkedMap = this.client.getMap_ucxLogInfoWorkedCalls();
// ObservableList<ChatMember> praktiKSTActiveUserList1 = this.client.getLst_chatMemberList();
//
// for (Iterator iterator = praktiKSTActiveUserList.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
//
// if (fetchedWorkedMap.containsKey(chatMember.getCallSign())) {
// chatMember.setWorked(true);
// System.out.println("[USERACT, info:] marking Chatuser " + chatMember.getCallSign() + " as worked based on UDP Log Info Collector.");
// }
// }
// ObservableList<ClusterMessage> praktiKSTClusterList1 = this.client.getLst_clusterMemberList();
//
// for (Iterator iterator = praktiKSTClusterList.iterator(); iterator.hasNext();) {
// ClusterMessage clusterMessage = (ClusterMessage) iterator.next();
//
// if (fetchedWorkedMap.containsKey(clusterMessage.getReceiver().getCallSign())) {
// clusterMessage.setReceiverWkd(true);
// System.out.println("[USERACT, info:] marking Clusterspotted "
// + clusterMessage.getReceiver().getCallSign() + " as worked based on UDP Log Info Collector.");
// }
//
// }
//
// UCXLogFileToHashsetParser getWorkedCallsignsOfUCXLogFile = new UCXLogFileToHashsetParser(
// "C:\\UcxLog\\Logs\\DO5AMF\\DVU322_I.UCX");
// try {
// fetchedWorkedSet = getWorkedCallsignsOfUCXLogFile.parse();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// ObservableList<ChatMember> praktiKSTActiveUserList = this.client.getLst_chatMemberList();
//
// for (Iterator iterator = praktiKSTActiveUserList.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
//
// if (fetchedWorkedSet.containsKey(chatMember.getCallSign())) {
// chatMember.setWorked(true);
// System.out.println("[USERACT, info:] marking Chatuser " + chatMember.getCallSign() + " as worked.");
// }
// }
//
//
// ObservableList<ClusterMessage> praktiKSTClusterList = this.client.getLst_clusterMemberList();
//
// for (Iterator iterator = praktiKSTClusterList.iterator(); iterator.hasNext();) {
// ClusterMessage clusterMessage = (ClusterMessage) iterator.next();
//
// if (fetchedWorkedSet.containsKey(clusterMessage.getReceiver().getCallSign())) {
// clusterMessage.setReceiverWkd(true);
// System.out.println("[USERACT, info:] marking Clusterspotted "
// + clusterMessage.getReceiver().getCallSign() + " as worked.");
// }
//
// }
/**
* ******************************************end here: new mechanic for marking
* worked stations by udp/adif based information
*
*/
// System.out.println("[UserActualizationtask:] Userlist actualization will be performed now. "
// + LocalDateTime.ofInstant(Instant.ofEpochMilli(scheduledExecutionTime()),
// ZoneId.systemDefault()));
// ChatMessage actualizeUserMsg = new ChatMessage();
// actualizeUserMsg.setDirectedToServer(true);
// actualizeUserMsg.setMessage("/show users");
// client.getMessageTXBus().add(actualizeUserMsg);
// Enumeration<String> e = this.client.getChatMemberTable().keys();
//
// while (e.hasMoreElements()) {
// String key = e.nextElement();
//
// System.out.println(this.client.getChatMemberTable().get(key).getCallSign() + ", "
// + this.client.getChatMemberTable().get(key).getQra() + ": "
// + this.client.getChatMemberTable().get(key).getFrequency());
//
// }
// System.out.println("[UserAct]: Show the Cluster with known frequencies now: ");
//
// Enumeration<String> e2 = this.client.getdXClusterMemberTable().keys();
//
// while (e2.hasMoreElements()) {
// String key = e2.nextElement();
//
// System.out.println(this.client.getdXClusterMemberTable().get(key).getCallSign() + ", "
// + this.client.getdXClusterMemberTable().get(key).getQra() + ": "
// + this.client.getdXClusterMemberTable().get(key).getFrequency());
//
// }
// for (int i = 0; i < 100; i++) {
//
// System.out.print("\n");
// }
/**
* keeepalive start
*/
// ChatMessage keepAliveMSG = new ChatMessage();
// keepAliveMSG.setMessageText("\r");
// keepAliveMSG.setMessageDirectedToServer(true);
//
// System.out.println(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() + " [UserAct]: Sending keepalive: "
// + keepAliveMSG.getMessageText());
// /**
// * Sending keepalive
// */
// this.client.getMessageTXBus().add(keepAliveMSG);
/**
* keeepalive end
*/
// System.out.println("[UserAct]: Show the Userlist with known frequencies sorted now: ");
// ObservableList<ChatMember> userlist = this.client.getLst_chatMemberList();
// for (Iterator iterator = userlist.iterator(); iterator.hasNext();) {
// ChatMember chatMember = (ChatMember) iterator.next();
// System.out.println("[Useract] Entry " + this.client.getLst_chatMemberList().indexOf(chatMember) + ": " + chatMember.getCallSign());
// }
//
// String chatMembers ="";
// SortedSet<String> keys = new TreeSet<>(this.client.getChatMemberTable().keySet());
// for (String key : keys) {
//
// chatMembers += this.client.getChatMemberTable().get(key).getCallSign() + ", "
// + this.client.getChatMemberTable().get(key).getName() + " in "
// + this.client.getChatMemberTable().get(key).getQra() + " @ QRG: "
// + this.client.getChatMemberTable().get(key).getFrequency() + "\n";
//
// System.out.println(this.client.getChatMemberTable().get(key).getCallSign() + ", "
// + this.client.getChatMemberTable().get(key).getName() + " in "
// + this.client.getChatMemberTable().get(key).getQra() + " @ QRG: "
// + this.client.getChatMemberTable().get(key).getFrequency());
// }
// System.out.println("\n[UserAct]: Show the Clusterlist with known frequencies sorted now: ");
// String dxcMembers ="";
// SortedSet<String> keys2 = new TreeSet<>(this.client.getdXClusterMemberTable().keySet());
// for (String key : keys2) {
// System.out.println(this.client.getdXClusterMemberTable().get(key).getCallSign() + " in "
// + this.client.getdXClusterMemberTable().get(key).getQra() + " @ QRG: "
// + this.client.getdXClusterMemberTable().get(key).getFrequency());
//
// dxcMembers += this.client.getdXClusterMemberTable().get(key).getCallSign() + " in "
// + this.client.getdXClusterMemberTable().get(key).getQra() + " @ QRG: "
// + this.client.getdXClusterMemberTable().get(key).getFrequency();
//
// }
// File userListLogger = new File(new Utils4KST().time_generateCurrentMMddString() + "_praktiKST_userlist.txt");
//
// FileWriter fileWriterRAWChatMSGOut = null;
//
// try {
// fileWriterRAWChatMSGOut = new FileWriter(userListLogger, true);
// } catch (IOException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
//
// BufferedWriter bufwrtrRawMSGOut;
//
// bufwrtrRawMSGOut = new BufferedWriter(fileWriterRAWChatMSGOut);
// System.out.println("#######################################" + chatMembers);
// try {
// bufwrtrRawMSGOut.write(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() + " " +this.client.getChatMemberTable().size() + " Chatmembers:\n" + chatMembers+ "\n");
// bufwrtrRawMSGOut.write(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() + " " + this.client.getdXClusterMemberTable().size() + " Clusterentries:\n" + dxcMembers + "\n");
// bufwrtrRawMSGOut.flush();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// try {
// bufwrtrRawMSGOut.close();
// } catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}

View File

@@ -0,0 +1,59 @@
package kst4contest.controller;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;
public class Utils4KST {
public long time_generateCurrentEpochTime() {
OffsetDateTime currentTimeInUtc = OffsetDateTime.now(ZoneOffset.UTC);
// System.out.println(currentTimeInUtc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm X")));
long millisecondsSinceEpoch = currentTimeInUtc.toInstant().toEpochMilli() / 1000;
// System.out.println(millisecondsSinceEpoch);
return millisecondsSinceEpoch;
}
public String time_generateCurrentMMDDhhmmTimeString() {
OffsetDateTime currentTimeInUtc = OffsetDateTime.now(ZoneOffset.UTC);
return currentTimeInUtc.format(DateTimeFormatter.ofPattern("MM-dd hh:mm"));
}
public String time_generateCurrentMMddString() {
OffsetDateTime currentTimeInUtc = OffsetDateTime.now(ZoneOffset.UTC);
return currentTimeInUtc.format(DateTimeFormatter.ofPattern("MM-dd"));
}
public String time_convertEpochToReadable(String epochFromServer) {
long epoch = Long.parseLong(epochFromServer);
// Instant instant = Instant.ofEpochSecond(epoch);
Date date = new Date(epoch * 1000L);
DateFormat format = new SimpleDateFormat("dd.MM HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String formatted = format.format(date);
// System.out.println("UTIL " + formatted);
return formatted;
}
public Date time_generateActualTimeInDateFormat() {
Date date = new Date(time_generateCurrentEpochTime() * 1000L);
return date;
}
}

View File

@@ -0,0 +1,255 @@
package kst4contest.controller;
import java.io.*;
import java.net.*;
import kst4contest.model.ChatMessage;
/**
* This thread is responsible for sending content to the chat. As we only use
* the tx function, there is no content in run() method
*
*
*/
public class WriteThread extends Thread {
private PrintWriter writer;
private Socket socket;
private ChatController client;
private OutputStream output;
private ChatMessage messageTextRaw;
public WriteThread(Socket socket, ChatController client) throws InterruptedException {
this.socket = socket;
this.client = client;
try {
output = socket.getOutputStream();
writer = new PrintWriter(output, true);
} catch (IOException ex) {
System.out.println("Error getting output stream: " + ex.getMessage());
ex.printStackTrace();
}
}
/**
* This method is used to send a message to the server, raw formatted. E.g. for
* the keepalive message.
*
* @param messageToServer
* @throws InterruptedException
*/
public void tx(ChatMessage messageToServer) throws InterruptedException {
// writer.println(messageToServer.getMessage()); //kst4contest.test 4 23001
// writer.flush(); //kst4contest.test 4 23001
System.out.println(messageToServer.getMessageText() + "< sended to the writer");
writer.println(messageToServer.getMessageText());
}
/**
* This method gets a textmessage to the chat and adds some characters to hit
* the neccessarry format to send a message in the on4kst chat either to another
* station or to the public.
*
* @param messageToServer
* @throws InterruptedException
*/
public void txKSTFormatted(ChatMessage messageToServer) throws InterruptedException {
// writer.println(messageToServer.getMessageText());
messageTextRaw = messageToServer;
try {
messageTextRaw = client.getMessageTXBus().take();
// this.client.getmesetChatsetServerready(true);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String messageLine = messageTextRaw.getMessageText();
if (messageTextRaw.isMessageDirectedToServer()) {
/**
* We have to check if we only commands the server (keepalive) or want do talk
* to the community
*/
try {
tx(messageTextRaw);
System.out.println("BUS: tx: " + messageTextRaw.getMessageText());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
ChatMessage ownMSG = new ChatMessage();
// ownMSG.setMessageText(
// "MSG|" + this.client.getCategory().getCategoryNumber() + "|0|" + messageLine + "|0|");
ownMSG.setMessageText("MSG|" + this.client.getChatPreferences().getLoginChatCategory().getCategoryNumber()
+ "|0|" + messageLine + "|0|");
try {
tx(ownMSG);
System.out.println("BUS: tx: " + ownMSG.getMessageText());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (messageTextRaw.equals("/QUIT")) {
try {
this.client.getReadThread().terminateConnection();
this.client.getReadThread().interrupt();
this.client.getWriteThread().terminateConnection();
this.client.getWriteThread().interrupt();
this.interrupt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public boolean terminateConnection() throws IOException {
this.output.close();
this.socket.close();
return true;
}
public void run() {
Thread.currentThread().setName("WriteToTelnetThread");
while (true) {
try {
messageTextRaw = client.getMessageTXBus().take();
if (messageTextRaw.getMessageText().equals("POISONPILL_KILLTHREAD")
&& messageTextRaw.getMessageSenderName().equals("POISONPILL_KILLTHREAD")) {
client.getMessageRXBus().clear();
this.interrupt();
break;
} else {
String messageLine = messageTextRaw.getMessageText();
if (messageTextRaw.isMessageDirectedToServer()) {
/**
* We have to check if we only commands the server (keepalive) or want do talk
* to the community
*/
try {
tx(messageTextRaw);
System.out.println("BUS: tx: " + messageTextRaw.getMessageText());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
ChatMessage ownMSG = new ChatMessage();
// ownMSG.setMessageText(
// "MSG|" + this.client.getCategory().getCategoryNumber() + "|0|" + messageLine + "|0|");
ownMSG.setMessageText(
"MSG|" + this.client.getChatPreferences().getLoginChatCategory().getCategoryNumber() + "|0|"
+ messageLine + "|0|");
try {
tx(ownMSG);
System.out.println("BUS: tx: " + ownMSG.getMessageText());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("WritheTh: got message out of the queue: " + messageTextRaw.getMessageText());
// this.client.getmesetChatsetServerready(true);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
client.getMessageTXBus().clear();
}
// String messageLine = messageTextRaw.getMessageText();
//
// if (messageTextRaw.isMessageDirectedToServer()) {
// /**
// * We have to check if we only commands the server (keepalive) or want do talk
// * to the community
// */
//
// try {
// tx(messageTextRaw);
// System.out.println("BUS: tx: " + messageTextRaw.getMessageText());
//
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// } else {
//
// ChatMessage ownMSG = new ChatMessage();
//
//// ownMSG.setMessageText(
//// "MSG|" + this.client.getCategory().getCategoryNumber() + "|0|" + messageLine + "|0|");
//
// ownMSG.setMessageText(
// "MSG|" + this.client.getChatPreferences().getLoginChatCategory().getCategoryNumber() + "|0|"
// + messageLine + "|0|");
//
// try {
// tx(ownMSG);
// System.out.println("BUS: tx: " + ownMSG.getMessageText());
//
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
}
// if (messageTextRaw.equals("/QUIT")) {
// try {
// this.client.getReadThread().terminateConnection();
// this.client.getReadThread().interrupt();
// this.client.getWriteThread().terminateConnection();
// this.client.getWriteThread().interrupt();
// this.interrupt();
//
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// while (true) {
//
// }
}
}

View File

@@ -0,0 +1,36 @@
package kst4contest.controller;
import java.util.TimerTask;
import kst4contest.model.ChatMessage;
public class keepAliveMessageSenderTask extends TimerTask {
private ChatController client;
public keepAliveMessageSenderTask(ChatController client) {
this.client = client;
}
@Override
public void run() {
Thread.currentThread().setName("KeepAliveMessageSenderTask");
// System.out.println("[keepalive: ] Thread runned now");
ChatMessage keepAliveMSG = new ChatMessage();
keepAliveMSG.setMessageText("\r");
keepAliveMSG.setMessageDirectedToServer(true);
// System.out.println(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() + " [keepaliveTask]: Sending keepalive: "
// + keepAliveMSG.getMessageText());
/**
* Sending keepalive
*/
this.client.getMessageTXBus().add(keepAliveMSG);
}
}

View File

@@ -0,0 +1,140 @@
package kst4contest.locatorUtils;
import java.math.BigDecimal;
import java.math.MathContext;
/**
* Allow for easy use of angles without messy conversions to and from degrees
* and radians.
*
* @author Paul Picazo <ppicazo@gmail.com>
*
*/
public class Angle {
/**
* pi.
*/
private static final BigDecimal BIG_PI = new BigDecimal(Math.PI);
/**
* representation of the angle in radians.
*/
protected BigDecimal radians;
/**
* no argument constructor.
*
*/
public Angle() {
}
/**
* @param radiansIn
* angle in radians
*/
public Angle(final double radiansIn) {
this.radians = new BigDecimal(radiansIn);
}
@Override
public int hashCode() {
final int prime = 7;
if (radians == null) {
return prime;
}
return prime + radians.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Angle)) {
return false;
}
return ((Angle) obj).hashCode() == this.hashCode();
}
/**
* @param degrees
* angle in degrees
* @return angle
*/
public static Angle fromDegrees(final double degrees) {
Angle angle = new Angle();
angle.radians = degreesToRadians(new BigDecimal(degrees),
MathContext.DECIMAL128);
return angle;
}
/**
* @param radiansIn
* the radians to set
*/
public void setRadians(final double radiansIn) {
this.radians = new BigDecimal(radiansIn);
}
/**
* @return the radians
*/
public double getRadians() {
return radians.doubleValue();
}
/**
* @return degrees
*/
public double toDegrees() {
return radiansToDegrees(this.radians, MathContext.DECIMAL128).doubleValue();
}
/**
* @param radians
* input
* @return degrees
*/
public static double radiansToDegrees(final double radians) {
return radiansToDegrees(new BigDecimal(radians), MathContext.DECIMAL128)
.doubleValue();
}
/**
* @param degrees
* input
* @return radians
*/
public static double degreesToRadians(final double degrees) {
return degreesToRadians(new BigDecimal(degrees), MathContext.DECIMAL128)
.doubleValue();
}
/**
* @param radians
* input
* @param mc
* MathContext for division
* @return degrees
*/
protected static BigDecimal radiansToDegrees(final BigDecimal radians,
final MathContext mc) {
return radians.multiply(new BigDecimal(180)).divide(BIG_PI, mc);
}
/**
* @param degrees
* input
* @param mc
* MathContext for division
* @return radians
*/
protected static BigDecimal degreesToRadians(final BigDecimal degrees,
final MathContext mc) {
return degrees.divide(new BigDecimal(180), mc).multiply(BIG_PI);
}
}

View File

@@ -0,0 +1,48 @@
package kst4contest.locatorUtils;
import java.math.BigDecimal;
import java.math.MathContext;
/**
* Latitude.
*
* @author Paul Picazo <ppicazo@gmail.com>
*
*/
public class Latitude extends Angle {
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj.getClass() == this.getClass())) {
return false;
}
return ((Latitude) obj).hashCode() == this.hashCode();
}
@Override
public int hashCode() {
final int prime = 37;
if (radians == null) {
return prime;
}
return prime + radians.hashCode();
}
/**
* @param degrees input
* @return latitude object
*/
public static Latitude fromDegrees(final double degrees) {
Latitude latitude = new Latitude();
latitude.radians = Angle.degreesToRadians(new BigDecimal(degrees),
MathContext.DECIMAL128);
return latitude;
}
}

View File

@@ -0,0 +1,305 @@
package kst4contest.locatorUtils;
/**
* Location class with methods allowing conversion to and from Maidenhead
* locator (grid squares) based off of
* "Conversion Between Geodetic and Grid Locator Systems" by Edmund T. Tyson,
* N5JTY in QST January 1989, pp. 29-30, 43
*
* @author Paul Picazo <ppicazo@gmail.com>
*
*/
public class Location {
/**
* Average earth radius in kilometers, IUGG definition.
*/
private static final double AVG_EARTH_RADIUS_KM = 6371.009;
/**
* Average earth radius in statute miles, IUGG definition.
*/
private static final double AVG_EARTH_RADIUS_SM = 3958.761;
/**
* Average earth radius in nautical miles, IUGG definition.
*/
private static final double AVG_EARTH_RADIUS_NM = 3440.069;
/**
* latitude of location.
*/
private Latitude latitude;
/**
* longitude of location.
*/
private Longitude longitude;
/**
* No argument constructor.
*
*/
public Location() {
this.latitude = new Latitude();
this.longitude = new Longitude();
}
/**
* @param latitudeIn
* initial latitude
* @param longitudeIn
* initial longitude
*/
public Location(final Latitude latitudeIn, final Longitude longitudeIn) {
this.latitude = latitudeIn;
this.longitude = longitudeIn;
}
/**
* @param latitudeIn
* initial latitude
* @param longitudeIn
* initial longitude
*/
public Location(final double latitudeIn, final double longitudeIn) {
this.latitude = Latitude.fromDegrees(latitudeIn);
this.longitude = Longitude.fromDegrees(longitudeIn);
}
/**
* @param maidenhead
* used construct location from maidenhead locator string
*/
public Location(final String maidenhead) {
this.latitude = extractLat(maidenhead);
this.longitude = extractLon(maidenhead);
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof Location) {
return ((Location) obj).hashCode() == this.hashCode();
}
return false;
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + this.latitude.hashCode();
hash = hash * 31 + this.longitude.hashCode();
return hash;
}
/**
* @return maidenhead locator string
*/
public String toMaidenhead() {
return toMaidenhead(this.latitude.toDegrees(),
this.longitude.toDegrees());
}
/**
* @param latitudeIn
* latitude component of locator string
* @param longitudeIn
* longitude component of locator string
* @return maidenhead locator string
*/
public static String toMaidenhead(final double latitudeIn,
final double longitudeIn) {
double longitude = longitudeIn + 180;
longitude /= 2;
char lonFirst = (char) ('A' + (longitude / 10));
char lonSecond = (char) ('0' + longitude % 10);
char lonThird = (char) ('A' + (longitude % 1) * 24);
double latitude = latitudeIn + 90;
char latFirst = (char) ('A' + (latitude / 10));
char latSecond = (char) ('0' + latitude % 10);
char latThird = (char) ('A' + (latitude % 1) * 24);
StringBuilder sb = new StringBuilder();
sb.append(lonFirst);
sb.append(latFirst);
sb.append(lonSecond);
sb.append(latSecond);
sb.append(("" + lonThird).toLowerCase());
sb.append(("" + latThird).toLowerCase());
return sb.toString();
}
/**
* @param maidenheadIn
* locator string to be converted
* @return latitude
*/
public static Latitude extractLat(final String maidenheadIn) {
String maidenhead = maidenheadIn.toUpperCase();
double latitude = -90 + 10 * (maidenhead.charAt(1) - 'A')
+ (maidenhead.charAt(3) - '0') + 2.5 / 60
* (maidenhead.charAt(5) - 'A') + 2.5 / 60 / 2;
return Latitude.fromDegrees(latitude);
}
/**
* @param maidenheadIn
* locator string to be converted
* @return longitude
*/
public static Longitude extractLon(final String maidenheadIn) {
String maidenhead = maidenheadIn.toUpperCase();
double longitude = -180 + 20 * (maidenhead.charAt(0) - 'A') + 2
* (maidenhead.charAt(2) - '0') + 5.0 / 60
* (maidenhead.charAt(4) - 'A') + 5.0 / 60 / 2;
return Longitude.fromDegrees(longitude);
}
/**
* @return latitude
*/
public Latitude getLatitude() {
return latitude;
}
/**
* @return longitude
*/
public Longitude getLongitude() {
return longitude;
}
/**
* @param latitudeIn
* north/south component of location
*/
public void setLatitude(final Latitude latitudeIn) {
this.latitude = latitudeIn;
}
/**
* @param longitudeIn
* east/west component of location
*/
public void setLongitude(final Longitude longitudeIn) {
this.longitude = longitudeIn;
}
/**
* @param loc2
* second location
* @return great circle distance in miles
*/
public double getDistanceMi(final Location loc2) {
return getDistanceMi(this, loc2);
}
/**
* @param loc2
* second location
* @return great circle distance in kilometers
*/
public double getDistanceKm(final Location loc2) {
return getDistanceKm(this, loc2);
}
/**
* @param loc2
* second location
* @return great circle distance in nautical miles
*/
public double getDistanceNm(final Location loc2) {
return getDistanceNm(this, loc2);
}
/**
* @param loc1
* first location
* @param loc2
* second location
* @return great circle distance in miles
*/
public static double getDistanceMi(final Location loc1, final Location loc2) {
return getDistance(loc1, loc2, AVG_EARTH_RADIUS_SM);
}
/**
* @param loc1
* first location
* @param loc2
* second location
* @return great circle distance in kilometers
*/
private static double getDistanceKm(final Location loc1, final Location loc2) {
return getDistance(loc1, loc2, AVG_EARTH_RADIUS_KM);
}
/**
* @param loc1
* first location
* @param loc2
* second location
* @return great circle distance in nautical miles
*/
private static double getDistanceNm(final Location loc1, final Location loc2) {
return getDistance(loc1, loc2, AVG_EARTH_RADIUS_NM);
}
/**
* @param loc1
* first location
* @param loc2
* second location
* @param radius
* radius of the earth in the units desired for result
* @return great circle distance between the two locations, result units same
* of the radius units
*/
private static double getDistance(final Location loc1, final Location loc2,
final double radius) {
if (loc1.equals(loc2)) {
return 0;
}
return Math.acos(Math.sin(loc1.getLatitude().getRadians())
* Math.sin(loc2.getLatitude().getRadians())
+ Math.cos(loc1.getLatitude().getRadians())
* Math.cos(loc2.getLatitude().getRadians())
* Math.cos(loc2.getLongitude().getRadians()
- loc1.getLongitude().getRadians()))
* radius;
}
/**
* @param loc2
* destination location
* @return bearing in degrees
*/
public double getBearing(final Location loc2) {
return getBearing(this, loc2);
}
/**
* @param loc1
* source location
* @param loc2
* destination location
* @return bearing in degrees
*/
public static double getBearing(final Location loc1, final Location loc2) {
if (loc1.equals(loc2)) {
return Double.NaN;
}
double dLon = loc2.getLongitude().getRadians()
- loc1.getLongitude().getRadians();
double y = Math.sin(dLon)
* Math.cos(loc2.getLatitude().getRadians());
double x = Math.cos(loc1.getLatitude().getRadians())
* Math.sin(loc2.getLatitude().getRadians())
- Math.sin(loc1.getLatitude().getRadians())
* Math.cos(loc2.getLatitude().getRadians())
* Math.cos(dLon);
return (Angle.radiansToDegrees(Math.atan2(y, x)) + 360) % 360;
}
}

View File

@@ -0,0 +1,49 @@
package kst4contest.locatorUtils;
import java.math.BigDecimal;
import java.math.MathContext;
/**
* Longitude.
*
* @author Paul Picazo <ppicazo@gmail.com>
*
*/
public class Longitude extends Angle {
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj.getClass() == this.getClass())) {
return false;
}
return ((Longitude) obj).hashCode() == this.hashCode();
}
@Override
public int hashCode() {
final int prime = 29;
if (radians == null) {
return prime;
}
return prime + radians.hashCode();
}
/**
* @param degrees input
* @return longitude object
*/
public static Longitude fromDegrees(final double degrees) {
Longitude longitude = new Longitude();
longitude.radians = Angle.degreesToRadians(new BigDecimal(degrees),
MathContext.DECIMAL128);
return longitude;
}
}

View File

@@ -0,0 +1,48 @@
package kst4contest.model;
public class AirPlane {
String apCallSign, apSizeCategory;
int distanceKm, potential, arrivingDurationMinutes;
public String getApCallSign() {
return apCallSign;
}
public void setApCallSign(String apCallSign) {
this.apCallSign = apCallSign;
}
public String getApSizeCategory() {
return apSizeCategory;
}
public void setApSizeCategory(String apSizeCategory) {
this.apSizeCategory = apSizeCategory;
}
public int getDistanceKm() {
return distanceKm;
}
public void setDistanceKm(int distanceKm) {
this.distanceKm = distanceKm;
}
public int getPotential() {
return potential;
}
public void setPotential(int potential) {
this.potential = potential;
}
public int getArrivingDurationMinutes() {
return arrivingDurationMinutes;
}
public void setArrivingDurationMinutes(int arrivingDurationMinutes) {
this.arrivingDurationMinutes = arrivingDurationMinutes;
}
@Override
public String toString() {
String toStringString = "\n";
toStringString += this.apCallSign + ", category: " + this.apSizeCategory + ", distance: " + this.getDistanceKm() + ", potential: " + this.potential + ", distance: " + this.getDistanceKm() + ", duration " + this.arrivingDurationMinutes + "" ;
return toStringString;
}
}

View File

@@ -0,0 +1,62 @@
package kst4contest.model;
import javafx.collections.ObservableList;
public class AirPlaneReflectionInfo {
String date;
ChatMember sender, receiver;
int airPlanesReachableCntr;
ObservableList<AirPlane> risingAirplanes;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public ChatMember getSender() {
return sender;
}
public void setSender(ChatMember sender) {
this.sender = sender;
}
public ChatMember getReceiver() {
return receiver;
}
public void setReceiver(ChatMember receiver) {
this.receiver = receiver;
}
public int getAirPlanesReachableCntr() {
return airPlanesReachableCntr;
}
public void setAirPlanesReachableCntr(int airPlanesReachableCntr) {
this.airPlanesReachableCntr = airPlanesReachableCntr;
}
public ObservableList<AirPlane> getRisingAirplanes() {
return risingAirplanes;
}
public void setRisingAirplanes(ObservableList<AirPlane> risingAirplanes) {
this.risingAirplanes = risingAirplanes;
}
@Override
public String toString() {
String toStringString = "";
toStringString += this.sender.getCallSign() + " > " + this.getReceiver().getCallSign() + " at " + this.getDate() + " " + this.airPlanesReachableCntr + " planes: " + this.getRisingAirplanes().toString();
return toStringString;
}
}

View File

@@ -0,0 +1,290 @@
package kst4contest.model;
/* 50/70 MHz..............1 <br/> 144/432 MHz............2<br/> Microwave..............3<br/>
* EME/JT65...............4 <br/> Low Band...............5 <br/> 50 MHz IARU Region 3...6 <br/> 50
* MHz IARU Region 2...7 <br/> 144/432 MHz IARU R 2...8 <br/> 144/432 MHz IARU R 3...9 <br/> kHz
* (2000-630m).......10 <br/> Warc (30,17,12m)......11 <br/> 28 MHz................12
* <br/>
* TODO: LowBand and khz need to be continued later...
*/
public class ChatCategory {
@Override
public String toString() {
String toStringString ="";
toStringString = this.getCategoryNumber()+": " + this.getChatCategoryName(categoryNumber);
return toStringString;
}
public static final int FIFTYSEVENTYMHz = 1;
public static final int VUHF = 2;
public static final int MICROWAVE = 3;
public static final int EMEJT65 = 4;
public static final int LOWBAND = 5;
public static final int FIFTYR3 = 6;
public static final int FIFTYR2 = 7;
public static final int VUHFR2 = 8;
public static final int VUHFR3 = 9;
public static final int KHZ2KM630M = 10;
public static final int WARC301712 = 11;
public static final int TENMeter = 12;
private int categoryNumber;
public int[] getPossibleCategoryNumbers() {
int[] possibleVals = new int[12];
possibleVals[0] = 1;
possibleVals[1] = 2;
possibleVals[2] = 3;
possibleVals[3] = 4;
possibleVals[4] = 5;
possibleVals[5] = 6;
possibleVals[6] = 7;
possibleVals[7] = 8;
possibleVals[8] = 9;
possibleVals[9] = 10;
possibleVals[10] = 11;
possibleVals[11] = 12;
return possibleVals;
}
public ChatCategory(int setThiscategoryNumber) {
this.categoryNumber = setThiscategoryNumber;
}
public int getCategoryNumber() {
return categoryNumber;
}
public void setCategoryNumber(int categoryNumber) {
this.categoryNumber = categoryNumber;
}
/**
* Returns an Array of int with possible frequency prefixes, due to in the chat
* normally the following format is used (not ever): <br/>
* "pse listen at .325"<br/>
* <br/>
*
* 50/70 MHz..............1 <br/>
* 144/432 MHz............2 <br/>
* Microwave..............3 <br/>
* EME/JT65...............4 <br/>
* Low Band...............5 <br/>
* 50 MHz IARU Region 3...6 <br/>
* 50 MHz IARU Region 2...7 <br/>
* 144/432 MHz IARU R 2...8 <br/>
* 144/432 MHz IARU R 3...9 <br/>
* kHz (2000-630m).......10 <br/>
* Warc (30,17,12m)......11 <br/>
* 28 MHz................12 <br/>
* TODO: LowBand and khz need to be continued later...
*
* @param int chatCategory (KST ChatCategory)
* @return Array of int with frequency prefixes, beginning with the lowest band
* (e.G. int[2] = [144, 430] for VUHF)
*/
public int[] getChatCategoryFrequencyPrefix(int chatCategory) {
int[] answer = new int[1];
answer[0] = 0;
switch (chatCategory) {
case ChatCategory.FIFTYSEVENTYMHz: {
answer = new int[2];
answer[0] = 50;
answer[1] = 70;
return answer;
}
case ChatCategory.VUHF: {
answer = new int[2];
answer[0] = 144;
answer[1] = 432;
return answer;
}
case ChatCategory.VUHFR2: {
answer = new int[2];
answer[0] = 144;
answer[1] = 432;
return answer;
}
case ChatCategory.VUHFR3: {
answer = new int[2];
answer[0] = 144;
answer[1] = 432;
return answer;
}
case ChatCategory.EMEJT65: { // 1296.2
answer = new int[13];
answer[0] = 144;
answer[1] = 432;
answer[2] = 1296;
answer[3] = 3400;
answer[4] = 5760;
answer[5] = 10368;
answer[6] = 24048;
answer[7] = 47000;
answer[8] = 77500;
answer[9] = 122250;
answer[10] = 134928;
answer[11] = 241920;
answer[12] = 453000;
return answer;
}
case ChatCategory.MICROWAVE: { // 1296.2
answer = new int[13];
answer[0] = 144;
answer[1] = 432;
answer[2] = 1296;
answer[3] = 3400;
answer[4] = 5760;
answer[5] = 10368;
answer[6] = 24048;
answer[7] = 47000;
answer[8] = 77500;
answer[9] = 122250;
answer[10] = 134928;
answer[11] = 241920;
answer[12] = 453000;
return answer;
}
case ChatCategory.TENMeter: {
answer = new int[1];
answer[0] = 28;
return answer;
}
case ChatCategory.WARC301712: {
answer = new int[3];
answer[0] = 10;
answer[1] = 18;
answer[2] = 24;
return answer;
}
default:
return answer;
}
};
/**
* Returns an Array of int with possible frequency prefixes, due to in the chat
* normally the following format is used (not ever): <br/>
* "pse listen at .325"<br/>
* <br/>
*
* 50/70 MHz..............1 <br/>
* 144/432 MHz............2 <br/>
* Microwave..............3 <br/>
* EME/JT65...............4 <br/>
* Low Band...............5 <br/>
* 50 MHz IARU Region 3...6 <br/>
* 50 MHz IARU Region 2...7 <br/>
* 144/432 MHz IARU R 2...8 <br/>
* 144/432 MHz IARU R 3...9 <br/>
* kHz (2000-630m).......10 <br/>
* Warc (30,17,12m)......11 <br/>
* 28 MHz................12 <br/>
* TODO: LowBand and khz need to be continued later...
*
* @param int chatCategory (KST ChatCategory)
* @return Array of int with frequency prefixes, beginning with the lowest band
* (e.G. int[2] = [144, 430] for VUHF)
*/
public String getChatCategoryName(int chatCategory) {
switch (chatCategory) {
case ChatCategory.FIFTYSEVENTYMHz: {
return "50/70 MHz";
}
case ChatCategory.FIFTYR2: {
return "50 MHz IARU Region 2";
}
case ChatCategory.FIFTYR3: {
return "50 MHz IARU Region 3";
}
case ChatCategory.LOWBAND: {
return "Low Band";
}
case ChatCategory.KHZ2KM630M: {
return "kHz (2000-630m)";
}
case ChatCategory.VUHF: {
return "144/432 MHz";
}
case ChatCategory.VUHFR2: {
return "144/432 MHz IARU R 2";
}
case ChatCategory.VUHFR3: {
return "144/432 MHz IARU R 3";
}
case ChatCategory.EMEJT65: { // 1296.2
return "EME/JT65";
}
case ChatCategory.MICROWAVE: { // 1296.2
return "Microwave";
}
case ChatCategory.TENMeter: {
return "28 MHz";
}
case ChatCategory.WARC301712: {
return "Warc (30,17,12m)";
}
default:
return "ERRROR: unknown";
}
};
}

View File

@@ -0,0 +1,270 @@
package kst4contest.model;
import java.util.Date;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class ChatMember {
AirPlaneReflectionInfo airPlaneReflectInfo;
String callSign;
String qra;
String name;
// String frequency; // last known qrg of the station
StringProperty frequency = new SimpleStringProperty();
String password; // only used by own instance of the chatmember instance to login to the chat
ChatCategory chatCategory; // only used by own instance of the chatmember instance to login to the chat
// ChatCategory chatCategory;//only used by own instance of the chatmember instance to login to the chat
long activityCounter; // time of last activity in epochtimesec
Date lastActivity; // time of last activity in epochtimesec
Date lastActualizationTimeOfThisMember; // time of last state change if that member
int qrb;
int state;
int QTFdirection; // antenna direction in deg
int[] workedCategories; // Chatcategory where the station is in the log, see kst4contest.model.ChatCategory
boolean worked; // true if the callsign is logged already - for temporary worked processing
boolean worked144;
boolean worked432;
boolean worked1240;
boolean worked2300;
boolean worked3400;
boolean worked5600;
boolean worked10G;
public AirPlaneReflectionInfo getAirPlaneReflectInfo() {
return airPlaneReflectInfo;
}
public void setAirPlaneReflectInfo(AirPlaneReflectionInfo airPlaneReflectInfo) {
this.airPlaneReflectInfo = airPlaneReflectInfo;
}
public ChatCategory getChatCategory() {
return chatCategory;
}
public void setChatCategory(ChatCategory chatCategory) {
this.chatCategory = chatCategory;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isWorked144() {
return worked144;
}
public void setWorked144(boolean worked144) {
this.worked144 = worked144;
}
public boolean isWorked432() {
return worked432;
}
public void setWorked432(boolean worked432) {
this.worked432 = worked432;
}
public boolean isWorked1240() {
return worked1240;
}
public void setWorked1240(boolean worked1240) {
this.worked1240 = worked1240;
}
public boolean isWorked2300() {
return worked2300;
}
public void setWorked2300(boolean worked2300) {
this.worked2300 = worked2300;
}
public boolean isWorked3400() {
return worked3400;
}
public void setWorked3400(boolean worked3400) {
this.worked3400 = worked3400;
}
public boolean isWorked5600() {
return worked5600;
}
public void setWorked5600(boolean worked5600) {
this.worked5600 = worked5600;
}
public boolean isWorked10G() {
return worked10G;
}
public void setWorked10G(boolean worked10g) {
worked10G = worked10g;
}
public int[] getWorkedCategories() {
return workedCategories;
}
public void setWorkedCategories(int[] workedCategories) {
this.workedCategories = workedCategories;
}
public void setActivityCounter(long activityCounter) {
this.activityCounter = activityCounter;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public Date getLastActivity() {
return lastActivity;
}
public void setLastActivity(Date lastActivity) {
this.lastActivity = lastActivity;
}
public Date getLastActualizationTimeOfThisMember() {
return lastActualizationTimeOfThisMember;
}
public void setLastActualizationTimeOfThisMember(Date lastActualizationTimeOfThisMember) {
this.lastActualizationTimeOfThisMember = lastActualizationTimeOfThisMember;
}
public int getQrb() {
return qrb;
}
public void setQrb(int qrb) {
this.qrb = qrb;
}
public int getQTFdirection() {
return QTFdirection;
}
public void setQTFdirection(int qTFdirection) {
QTFdirection = qTFdirection;
}
// public int getWorkedCategory() {
// return workedCategory;
// }
// public void setWorkedCategory(int workedCategory) {
// this.workedCategory = workedCategory;
// }
public String getCallSign() {
return callSign;
}
public void setCallSign(String callSign) {
this.callSign = callSign;
}
public String getQra() {
return qra;
}
public void setQra(String qra) {
this.qra = qra;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public StringProperty getFrequency() {
return frequency;
// return frequency;
}
public void setFrequency(StringProperty frequency) {
this.frequency = frequency;
}
public long getActivityCounter() {
return activityCounter;
}
public void setActivityCounter(int activityCounter) {
this.activityCounter = activityCounter;
}
public boolean isWorked() {
return worked;
}
public void setWorked(boolean worked) {
this.worked = worked;
}
/**
* Sets all worked information of this object to false. Scope: GUI, Reset Button
* for worked info, called by appcontroller
*/
public void resetWorkedInformationAtAllBands() {
this.setWorked(false);
this.setWorked144(false);
this.setWorked432(false);
this.setWorked1240(false);
this.setWorked2300(false);
this.setWorked3400(false);
this.setWorked5600(false);
this.setWorked10G(false);
}
@Override
public String toString() {
String chatMemberSerialization = "";
chatMemberSerialization += callSign + ";" + name + ";" + qra + ";" + frequency + ";" + worked + ";" + worked144
+ ";" + worked432 + ";" + worked1240 + ";" + worked2300 + ";" + worked3400 + ";" + worked5600 + ";"
+ worked10G;
return chatMemberSerialization;
}
/**
* Finds out if a given Chatmember-instance has the same callsign as this
* instance. Callsign is used as a key.
*
* @param anotherChatMember
* @return
*/
public boolean equals(ChatMember anotherChatMember) {
if (this.getCallSign().toUpperCase().equals(anotherChatMember.getCallSign().toUpperCase())) {
return true;
} else
return false;
}
}

View File

@@ -0,0 +1,90 @@
package kst4contest.model;
//import java.time.OffsetDateTime;
/**
* boolean directedToServer is important
* @author mywire
*
*/
public class ChatMessage {
ChatMember sender;
String messageText;
ChatMember receiver; //the callsign to whom the message is directed
String messageGeneratedTime; //generated time in epochtimemillis/1000, as used by the chatserver
ChatCategory chatCategory;
String messageSenderName;
boolean messageByServer; //whether the chat message is directed do the server
boolean messageDirectedToCommunity; //wheter the message is directed to anyone or to all users
boolean messageDirectedToMe; //wheter message is directed to the praktiKST User
boolean messageDirectedToServer;
public boolean isMessageDirectedToServer() {
return messageDirectedToServer;
}
public void setMessageDirectedToServer(boolean messageDirectedToServer) {
this.messageDirectedToServer = messageDirectedToServer;
}
public boolean isMessageDirectedToCommunity() {
return messageDirectedToCommunity;
}
public void setMessageDirectedToCommunity(boolean messageDirectedToCommunity) {
this.messageDirectedToCommunity = messageDirectedToCommunity;
}
public boolean isMessageDirectedToMe() {
return messageDirectedToMe;
}
public void setMessageDirectedToMe(boolean messageDirectedToMe) {
this.messageDirectedToMe = messageDirectedToMe;
}
public String getMessageSenderName() {
return messageSenderName;
}
public void setMessageSenderName(String messageSenderName) {
this.messageSenderName = messageSenderName;
}
public ChatCategory getChatCategory() {
return chatCategory;
}
public void setChatCategory(ChatCategory chatCategory) {
this.chatCategory = chatCategory;
}
public boolean isMessageByServer() {
return messageByServer;
}
public void setMessageByServer(boolean isMessageByServer) {
this.messageByServer = isMessageByServer;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public String getMessageGeneratedTime() {
return messageGeneratedTime;
}
public void setMessageGeneratedTime(String messageGeneratedTime) {
this.messageGeneratedTime = messageGeneratedTime;
}
public ChatMember getSender() {
return sender;
}
public void setSender(ChatMember sender) {
this.sender = sender;
}
public String getMessageText() {
return messageText;
}
public ChatMember getReceiver() {
return receiver;
}
public void setReceiver(ChatMember receiver) {
this.receiver = receiver;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
package kst4contest.model;
public class ClusterMessage {
String timeGenerated;
ChatMember sender;
ChatMember receiver;
String qrgSpotted;
String qraOfSender;
String qraOfReceiver;
String messageInhibited;
boolean receiverWkd;
public boolean isReceiverWkd() {
return receiverWkd;
}
public void setReceiverWkd(boolean receiverWkd) {
this.receiverWkd = receiverWkd;
}
public String getTimeGenerated() {
return timeGenerated;
}
public void setTimeGenerated(String timeGenerated) {
this.timeGenerated = timeGenerated;
}
public ChatMember getSender() {
return sender;
}
public void setSender(ChatMember sender) {
this.sender = sender;
}
public ChatMember getReceiver() {
return receiver;
}
public void setReceiver(ChatMember receiver) {
this.receiver = receiver;
}
public String getQrgSpotted() {
return qrgSpotted;
}
public void setQrgSpotted(String qrgSpotted) {
this.qrgSpotted = qrgSpotted;
}
public String getQraOfSender() {
return qraOfSender;
}
public void setQraOfSender(String qraOfSender) {
this.qraOfSender = qraOfSender;
}
public String getQraOfReceiver() {
return qraOfReceiver;
}
public void setQraOfReceiver(String qraOfReceiver) {
this.qraOfReceiver = qraOfReceiver;
}
public String getMessageInhibited() {
return messageInhibited;
}
public void setMessageInhibited(String messageInhibited) {
this.messageInhibited = messageInhibited;
}
}

View File

@@ -0,0 +1,15 @@
package kst4contest.view;
public class GuiUtils {
/**
* Checks wheter the input value of the String is numeric or not, true if yes
* TODO: Move to a utils class for checking input values by user...
* @param str
* @return
*/
static boolean isNumeric(String str){
return str != null && str.matches("[0-9.]+");
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<praktiKST>
<station>
<LoginCallSign>DO5SA</LoginCallSign>
<LoginPassword>kst4contest.test</LoginPassword>
<LoginDisplayedName>Paule</LoginDisplayedName>
<LoginLocator>JO51DI</LoginLocator>
<ChatCategory>2</ChatCategory>
</station>
<logsynch>
<logsynch_fileBasedWkdCallInterpreterFileNameReadOnly>SimpleLogFile.txt</logsynch_fileBasedWkdCallInterpreterFileNameReadOnly>
<logsynch_storeWorkedCallSignsFileNameUDPMessageBackup>udpReaderBackup.txt</logsynch_storeWorkedCallSignsFileNameUDPMessageBackup>
<logsynch_fileBasedWkdCallInterpreterEnabled>true</logsynch_fileBasedWkdCallInterpreterEnabled>
<logsynch_ucxUDPWkdCallListenerPort>12060</logsynch_ucxUDPWkdCallListenerPort>
<logsynch_ucxUDPWkdCallListenerEnabled>true</logsynch_ucxUDPWkdCallListenerEnabled>
</logsynch>
<trxSynchUCX>
<trxSynch_ucxLogUDPListenerEnabled>true</trxSynch_ucxLogUDPListenerEnabled>
<trxSynch_defaultMYQRGValue>144.010.00</trxSynch_defaultMYQRGValue>
</trxSynchUCX>
<AirScoutQuerier>
<asQry_airScoutCommunicationEnabled>true</asQry_airScoutCommunicationEnabled>
<asQry_airScoutServerName>KST</asQry_airScoutServerName>
<asQry_airScoutClientName>KST</asQry_airScoutClientName>
<asQry_airScoutUDPPort>9872</asQry_airScoutUDPPort>
<asQry_airScoutBandValue>1440000</asQry_airScoutBandValue>
</AirScoutQuerier>
<shortCuts>
<t>Hi OM,</t>
<t>pse</t>
<t>turn</t>
<t>ant</t>
<t>my</t>
<t>dir</t>
<t>sked</t>
<t>ssb</t>
<t>cw</t>
<t>try</t>
<t>agn</t>
<t>nw</t>
<t>qrg</t>
<t>beaming</t>
<t>calling</t>
<t>lsn to</t>
<t>qsb</t>
<t>rpt</t>
<t>nr</t>
<t>ur</t>
<t>I</t>
<t>hear</t>
<t>you</t>
<t>weak</t>
<t>nil, sry</t>
<t>maybe</t>
<t>later</t>
<t>tmw</t>
<t>rrr</t>
<t>tnx</t>
<t>qso</t>
<t>73</t>
<t>?</t>
<t>!</t>
<t>,</t>
<t>/SETNAME MYQRG</t>
<t>MYQRG</t>
</shortCuts>
<textSnippets>
<t>Hi OM, try sked 2m? Ur QRG?</t>
<t>Hi OM, try sked 70cms? Ur QRG?</t>
<t>Hi OM, try sked 23cms? Ur QRG?</t>
<t>I am calling cq to ur dir, pse lsn to MYLOCATOR at MYQRG</t>
<t>pse ur qrg?</t>
<t>rrr, I move to your qrg nw, pse ant dir MYLOCATOR</t>
<t>Hrd you but many qrm here, pse agn</t>
<t>I turn my ant to you now</t>
<t>Sry, strong qrm by local station, may try MYQRG</t>
<t>Sry, in qso nw, pse qrx, I will meep you</t>
<t>Ur ant my dir MYLOCATOR nw?</t>
<t>nil?</t>
<t>No cw op here, pse can we use ssb?</t>
<t>No chance in ssb, can we use cw?</t>
<t>Nil till now, are you calling?</t>
<t>Nil here, tnx try, maybe later!</t>
<t>Nil, I will look for an ap and meep you then</t>
<t>There will be an AP in </t>
<t>Tnx fb qso, all ok, 73 es gl!</t>
</textSnippets>
<beaconCQ>
<beaconCQText>_.~'"´"'~.__.~'´ CQ CQ CQ de MYCALL, pse call us at MYQRG `'~.__.~'"`"'~._</beaconCQText>
<beaconCQIntervalMinutes>5</beaconCQIntervalMinutes>
<beaconCQEnabled>false</beaconCQEnabled>
</beaconCQ>
<beaconUnworkedstations>
<beaconUnworkedstationsText>Hi OM, pse Sked at MYQRG or your QRG</beaconUnworkedstationsText>
<beaconUnworkedstationsIntervalMinutes>20</beaconUnworkedstationsIntervalMinutes>
<beaconUnworkedstationsEnabled>false</beaconUnworkedstationsEnabled>
<beaconUnworkedstationsPrefix>OE</beaconUnworkedstationsPrefix>
</beaconUnworkedstations>
</praktiKST>

View File

@@ -0,0 +1,18 @@
package kst4contest.test;
import kst4contest.model.ChatPreferences;
import org.junit.jupiter.api.Test;
public class TestChatPreferences {
@Test
public static void main(String[] args) {
ChatPreferences prefs = new ChatPreferences();
prefs.readPreferencesFromXmlFile(); //works
prefs.writePreferencesToXmlFile(); //works
}
}

View File

@@ -0,0 +1,27 @@
package kst4contest.test;
import kst4contest.controller.ReadUDPbyAirScoutMessageThread;
import org.junit.jupiter.api.Test;
public class TestReadUDPASListenerThread {
@Test
public static void main(String[] args) {
ReadUDPbyAirScoutMessageThread asUDPReader = new ReadUDPbyAirScoutMessageThread(9872, null, "AS", "KST");
asUDPReader.start();
String testThis;
// testThis = "ASNEAREST: \"AS\" \"KST\" \"2023-04-01 21:33:42Z,DO5AMF,JN49GL,G4CLA,IO92JL,9,VLG2PT,M,190,75,14,BAW809,M,250,50,18,BEL6CM,M,143,50,12,WZZ6719,M,148,50,11,KLM1678,M,313,75,22,TRA1B,M,271,75,20,SAS4728,M,125,75,9,RYR6TL,M,90,75,6,UAE10,S,96,50,6\"";
// asUDPReader.processASUDPMessage(testThis);
// ucxUDPReader.processUCXUDPMessage(testThis);
// ucxUDPReader =new ReadUDPbyUCXMessageThread(12060);
// ucxUDPReader.processUCXUDPMessage(testThis);
}
}

View File

@@ -0,0 +1,82 @@
package kst4contest.test;
import kst4contest.controller.ReadUDPbyUCXMessageThread;
import org.junit.jupiter.api.Test;
public class TestReadUDPUCXListenerThread {
@Test
public static void main(String[] args) {
ReadUDPbyUCXMessageThread ucxUDPReader = new ReadUDPbyUCXMessageThread(12060);
ucxUDPReader.start();
String testThis;
testThis = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<contactinfo>\r\n"
+ " <app>UcxLog</app>\r\n"
+ " <contestname></contestname>\r\n"
+ " <contestnr></contestnr>\r\n"
+ " <timestamp>2022-10-30 11:51:00</timestamp>\r\n"
+ " <mycall>DO5AMF</mycall>\r\n"
+ " <band>144</band>\r\n"
+ " <rxfreq>14400000</rxfreq>\r\n"
+ " <txfreq>14400000</txfreq>\r\n"
+ " <operator></operator>\r\n"
+ " <mode>USB</mode>\r\n"
+ " <call>DM1AO</call>\r\n"
+ " <countryprefix></countryprefix>\r\n"
+ " <wpxprefix></wpxprefix>\r\n"
+ " <stationprefix></stationprefix>\r\n"
+ " <continent>EU</continent>\r\n"
+ " <snt>59</snt>\r\n"
+ " <sntnr>021 JN49FK</sntnr>\r\n"
+ " <rcv>59</rcv>\r\n"
+ " <rcvnr>001 JO50LT</rcvnr>\r\n"
+ " <gridsquare></gridsquare>\r\n"
+ " <exchange1></exchange1>\r\n"
+ " <section></section>\r\n"
+ " <comment></comment>\r\n"
+ " <qth></qth>\r\n"
+ " <name></name>\r\n"
+ " <power></power>\r\n"
+ " <misctext></misctext>\r\n"
+ " <zone>0</zone>\r\n"
+ " <prec></prec>\r\n"
+ " <ck>0</ck>\r\n"
+ " <ismultiplierl></ismultiplierl>\r\n"
+ " <ismultiplier2></ismultiplier2>\r\n"
+ " <ismultiplier3></ismultiplier3>\r\n"
+ " <points></points>\r\n"
+ " <radionr>1</radionr>\r\n"
+ " <run1run2>1</run1run2>\r\n"
+ " <RoverLocation></RoverLocation>\r\n"
+ " <RadioInterfaced>0</RadioInterfaced>\r\n"
+ " <NetworkedCompNr>0</NetworkedCompNr>\r\n"
+ " <IsOriginal>True</IsOriginal>\r\n"
+ " <NetBiosName></NetBiosName>\r\n"
+ " <IsRunQSO>0</IsRunQSO>\r\n"
+ " <StationName>LAPTOP-05GRNFHI</StationName>\r\n"
+ " <ID>0C73B5B3B82C4836</ID>\r\n"
+ " <IsClaimedQso>True</IsClaimedQso>\r\n"
+ "</contactinfo> ";
// ucxUDPReader.processUCXUDPMessage(testThis);
testThis ="<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"
+ "<RadioInfo>\r\n"
+ " <app>UcxLog</app>\r\n"
+ " <RadioNr>1</RadioNr>\r\n"
+ " <Freq>2101100</Freq>\r\n"
+ " <TXFreq>2101100</TXFreq>\r\n"
+ " <Mode>CW</Mode>\r\n"
+ " <IsSplit>False</IsSplit>\r\n"
+ "</RadioInfo>";
// ucxUDPReader =new ReadUDPbyUCXMessageThread(12060);
// ucxUDPReader.processUCXUDPMessage(testThis);
}
}

View File

@@ -0,0 +1,24 @@
package kst4contest.test;
import java.io.IOException;
import kst4contest.controller.UCXLogFileToHashsetParser;
import org.junit.jupiter.api.Test;
public class TestUCXLogFileToHashsetParser {
@Test
public static void main(String[] args) {
// TODO Auto-generated method stub
UCXLogFileToHashsetParser testTheParser = new UCXLogFileToHashsetParser("C:\\UcxLog\\Logs\\DO5AMF\\DVU322_I.UCX");
try {
testTheParser.parse();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,44 @@
package kst4contest.test;
import org.junit.jupiter.api.Test;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPAirScoutSendMessages {
@Test
public static void main(String args[]) {
try {
// String host = "www.java2s.com";
// byte[] message = "ASWATCHLIST: \"KST\" \"AS\" 1440000,DO5AMF,JN49GL,OK1MZM,JN89IW ".getBytes();
// Get the internet address of the specified host
// InetAddress address = InetAddress.getByName(host);^
// byte[] byteAddress = "127.0.0.1".getBytes();
// System.out.println(byteAddress.length);
String host = "255.255.255.255";
int port = 9872;
byte[] message = "ASSETPATH: \"KST\" \"AS\" 1440000,DO5AMF,JN49GL,OK1MZM,JN89IW ".getBytes();
InetAddress address = InetAddress.getByName("255.255.255.255");
// Initialize a datagram packet with data and address
DatagramPacket packet = new DatagramPacket(message, message.length,
address, port);
// Create a datagram socket, send the packet through it, close it.
DatagramSocket dsocket = new DatagramSocket();
dsocket.setBroadcast(true);
dsocket.send(packet);
dsocket.close();
} catch (Exception e) {
System.err.println(e);
}
}
}

View File

@@ -0,0 +1,15 @@
package kst4contest.test;
import kst4contest.controller.Utils4KST;
import org.junit.jupiter.api.Test;
public class testTimeGeneration {
@Test
public static void main(String[] args) {
System.out.println(new Utils4KST().time_convertEpochToReadable("1664669836"));
}
}