diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2ca9e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Fleet IDE +.fleet + +# Intellij +.idea +*.iml + +# Eclipse +.project +.classpath + +# Maven +target + + +debug.out +.DS_Store + diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..3c6fda8 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/SimpleLogFile.txt b/SimpleLogFile.txt new file mode 100644 index 0000000..1f82eed --- /dev/null +++ b/SimpleLogFile.txt @@ -0,0 +1 @@ +do5sa \ No newline at end of file diff --git a/lib/javafx-swt.jar b/lib/javafx-swt.jar new file mode 100644 index 0000000..c1e132f Binary files /dev/null and b/lib/javafx-swt.jar differ diff --git a/lib/javafx.base.jar b/lib/javafx.base.jar new file mode 100644 index 0000000..872eae0 Binary files /dev/null and b/lib/javafx.base.jar differ diff --git a/lib/javafx.controls.jar b/lib/javafx.controls.jar new file mode 100644 index 0000000..2819d75 Binary files /dev/null and b/lib/javafx.controls.jar differ diff --git a/lib/javafx.fxml.jar b/lib/javafx.fxml.jar new file mode 100644 index 0000000..f46d1fb Binary files /dev/null and b/lib/javafx.fxml.jar differ diff --git a/lib/javafx.graphics.jar b/lib/javafx.graphics.jar new file mode 100644 index 0000000..f7f74b1 Binary files /dev/null and b/lib/javafx.graphics.jar differ diff --git a/lib/javafx.media.jar b/lib/javafx.media.jar new file mode 100644 index 0000000..dd39afa Binary files /dev/null and b/lib/javafx.media.jar differ diff --git a/lib/javafx.properties b/lib/javafx.properties new file mode 100644 index 0000000..5496314 --- /dev/null +++ b/lib/javafx.properties @@ -0,0 +1,3 @@ +javafx.version=19 +javafx.runtime.version=19+11 +javafx.runtime.build=11 diff --git a/lib/javafx.swing.jar b/lib/javafx.swing.jar new file mode 100644 index 0000000..886d72f Binary files /dev/null and b/lib/javafx.swing.jar differ diff --git a/lib/javafx.web.jar b/lib/javafx.web.jar new file mode 100644 index 0000000..5bd5928 Binary files /dev/null and b/lib/javafx.web.jar differ diff --git a/lib/sqlite-jdbc-3.39.3.0.jar b/lib/sqlite-jdbc-3.39.3.0.jar new file mode 100644 index 0000000..23ab073 Binary files /dev/null and b/lib/sqlite-jdbc-3.39.3.0.jar differ diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..8d937f4 --- /dev/null +++ b/mvnw @@ -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 "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..c4586b5 --- /dev/null +++ b/mvnw.cmd @@ -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% diff --git a/pmd-ruleset.xml b/pmd-ruleset.xml new file mode 100644 index 0000000..9fe4fb7 --- /dev/null +++ b/pmd-ruleset.xml @@ -0,0 +1,37 @@ + + + + + + Custom ruleset for Java + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..52e53b5 --- /dev/null +++ b/pom.xml @@ -0,0 +1,460 @@ + + + 4.0.0 + + de.x08 + praktiKST + 1.0-SNAPSHOT + + praktiKST + + + DO5AMF + + + http://www.x08.de + + jar + + + + ${project.artifactId} + ${project.artifactId} + ${project.artifactId} + kst4contest.view.Kst4ContestApplication + 17 + 3.6.3 + ${project.artifactId}-${project.version} + + + 19.0.2.1 + 24.0.1 + 5.10.1 + 1.18.30 + 5.7.0 + 3.43.2.2 + + + 3.3.2 + 3.11.0 + 3.3.0 + 3.1.1 + 3.4.1 + 3.1.1 + 3.3.0 + 3.3.1 + 4.0.0-M11 + 3.2.2 + 3.2.0 + 1.0.0.RC2 + 0.1.3 + 3.21.2 + 6.55.0 + 2.16.1 + 0.0.8 + 4.8.1.0 + 4.8.1 + + + UTF-8 + ${java.version} + ${java.version} + ${java.version} + VERBOSE + + + + + + org.openjfx + javafx-controls + ${javafx.version} + + + org.openjfx + javafx-graphics + ${javafx.version} + + + org.openjfx + javafx-fxml + ${javafx.version} + + + org.openjfx + javafx-web + ${javafx.version} + + + org.openjfx + javafx-media + ${javafx.version} + + + + + org.xerial + sqlite-jdbc + ${sqlite.version} + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + + + + + org.jetbrains + annotations + ${jetbrains.annotations.version} + compile + + + + + + + + ${jar.filename} + + + org.apache.maven.plugins + maven-wrapper-plugin + ${maven.wrapper.plugin} + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven.enforcer.plugin} + + + enforce-versions + + enforce + + + + + ${required.maven.version} + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin} + + ${java.version} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + org.apache.maven.plugins + maven-clean-plugin + ${maven.clean.plugin} + + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven.deploy.plugin} + + + + org.apache.maven.plugins + maven-install-plugin + ${maven.install.plugin} + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven.jar.plugin} + + + + org.apache.maven.plugins + maven-resources-plugin + ${maven.resources.plugin} + + + + org.apache.maven.plugins + maven-site-plugin + ${maven.site.plugin} + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surfire.plugin} + + true + + + + + com.github.spotbugs + spotbugs-maven-plugin + ${spotbugs.maven.plugin} + + + + com.github.spotbugs + spotbugs + ${spotbugs.version} + + + + + prepare-package + + + spotbugs + + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + ${maven.pmd.version} + + + net.sourceforge.pmd + pmd-core + ${pmd.version} + + + net.sourceforge.pmd + pmd-java + ${pmd.version} + + + net.sourceforge.pmd + pmd-javascript + ${pmd.version} + + + net.sourceforge.pmd + pmd-jsp + ${pmd.version} + + + + ${project.build.sourceEncoding} + 100 + ${java.version} + false + + pmd-ruleset.xml + + + + + prepare-package + + + pmd + + + + + + + + + + org.codehaus.mojo + versions-maven-plugin + ${codehaus.version.plugin} + + + validate + + display-dependency-updates + display-plugin-updates + display-property-updates + + + + + + + + org.openjfx + javafx-maven-plugin + ${javafx.maven.plugin} + + ${main.class} + + + + + + + + + + + Image + + + Image + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven.dependency.plugin} + + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/modules + runtime + false + false + true + + + + + + copy + install + + copy + + + ${project.build.directory}/modules + + + ${project.groupId} + ${project.artifactId} + ${project.version} + ${project.packaging} + ${project.build.finalName}.jar + + + true + + + + + + + com.github.akman + jpackage-maven-plugin + ${jpackage.maven.plugin} + + ${appName} + IMAGE + + + + + javafx\..* + + + + + + javafx.controls + javafx.graphics + javafx.fxml + javafx.web + java.sql + + ${main.class} + ${project.build.directory}/modules + ${jar.filename}.jar + + + + install + + jpackage + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/kst4contest/ApplicationConstants.java b/src/main/java/kst4contest/ApplicationConstants.java new file mode 100644 index 0000000..6fcd828 --- /dev/null +++ b/src/main/java/kst4contest/ApplicationConstants.java @@ -0,0 +1,8 @@ +package kst4contest; + +public class ApplicationConstants { + /** + * Name of the Application. + */ + public static final String APPLICATION_NAME = "praktiKST"; +} diff --git a/src/main/java/kst4contest/controller/AirScoutPeriodicalAPReflectionInquirerTask.java b/src/main/java/kst4contest/controller/AirScoutPeriodicalAPReflectionInquirerTask.java new file mode 100644 index 0000000..eff506d --- /dev/null +++ b/src/main/java/kst4contest/controller/AirScoutPeriodicalAPReflectionInquirerTask.java @@ -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 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� + * 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); + + + } + +} diff --git a/src/main/java/kst4contest/controller/AppRunner.java b/src/main/java/kst4contest/controller/AppRunner.java new file mode 100644 index 0000000..36907e3 --- /dev/null +++ b/src/main/java/kst4contest/controller/AppRunner.java @@ -0,0 +1,13 @@ +package kst4contest.controller; + +import kst4contest.view.Kst4ContestApplication; + +public class AppRunner { + + public static void main(String[] args) { + + Kst4ContestApplication.main(args); + + } + +} diff --git a/src/main/java/kst4contest/controller/BeaconTask.java b/src/main/java/kst4contest/controller/BeaconTask.java new file mode 100644 index 0000000..8c823f4 --- /dev/null +++ b/src/main/java/kst4contest/controller/BeaconTask.java @@ -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. + *

+ * 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 + } + + + } + +} diff --git a/src/main/java/kst4contest/controller/ChatController.java b/src/main/java/kst4contest/controller/ChatController.java new file mode 100644 index 0000000..9d70464 --- /dev/null +++ b/src/main/java/kst4contest/controller/ChatController.java @@ -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.
+ * SINGLETON + * + */ +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 messageRXBus; // Queue in which all Chatmessages are buffered, sources are + // read- and write-thread + private LinkedBlockingQueue 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 chatMemberTable = new Hashtable(); +// private HashMap chatMemberTable = new HashMap(); +// private Hashtable dXClusterMemberTable = new Hashtable(); + + private ObservableList lst_toAllMessageList = FXCollections.observableArrayList(); // directed to all + // (beacon) + private ObservableList lst_toMeMessageList = FXCollections.observableArrayList(); // directed to my + // call + private ObservableList lst_toOtherMessageList = FXCollections.observableArrayList(); // directed to a + // call but not + // mine + private ObservableList chatMemberList = FXCollections.observableArrayList(); // List of active stations + // in chat + private ObservableList lst_chatMemberList = FXCollections.synchronizedObservableList(chatMemberList); // List + // of + // active + // stations + // in + // chat + private ObservableList lst_clusterMemberList = FXCollections.observableArrayList(); + + private ObservableList lst_DBBasedWkdCallSignList = FXCollections.observableArrayList(); + +// private HashMap map_ucxLogInfoWorkedCalls = new HashMap(); //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, if not, + * returns -1. + * + * @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 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 getLst_chatMemberList() { + return lst_chatMemberList; + } + + public ObservableList getLst_DBBasedWkdCallSignList() { + return lst_DBBasedWkdCallSignList; + } + + public void setLst_DBBasedWkdCallSignList(ObservableList lst_DBBasedWkdCallSignList) { + this.lst_DBBasedWkdCallSignList = lst_DBBasedWkdCallSignList; + } + + public void setLst_chatMemberList(ObservableList lst_chatMemberList) { + this.lst_chatMemberList = lst_chatMemberList; + } + + public ObservableList getLst_clusterMemberList() { + return lst_clusterMemberList; + } + + public void setLst_clusterMemberList(ObservableList lst_clusterMemberList) { + this.lst_clusterMemberList = lst_clusterMemberList; + } + + public ObservableList getLst_toAllMessageList() { + return lst_toAllMessageList; + } + + public void setLst_toAllMessageList(ObservableList lst_toAllMessageList) { + this.lst_toAllMessageList = lst_toAllMessageList; + } + + public ObservableList getLst_toMeMessageList() { + return lst_toMeMessageList; + } + + public void setLst_toMeMessageList(ObservableList lst_toMeMessageList) { + this.lst_toMeMessageList = lst_toMeMessageList; + } + + public ObservableList getLst_toOtherMessageList() { + return lst_toOtherMessageList; + } + + public void setLst_toOtherMessageList(ObservableList lst_toOtherMessageList) { + this.lst_toOtherMessageList = lst_toOtherMessageList; + } + + public LinkedBlockingQueue 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 getMessageRXBus() { + return messageRXBus; + } + + public void setMessageRXBus(LinkedBlockingQueue 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 chatMemberTable) { +// this.chatMemberTable = chatMemberTable; +// } +// +// public void setChatMemberTable(HashMap 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(); + messageTXBus = new LinkedBlockingQueue(); +// 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
+ *
+ * Login parameter format is like that:
+ * LOGINC|do5amf|uxskezcj|2|wtKST 3.1.4.6|25|0|1|1663879818|0|
+ * SDONE|2|
+ * + * @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 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(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 + } + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/controller/DBController.java b/src/main/java/kst4contest/controller/DBController.java new file mode 100644 index 0000000..a348bf6 --- /dev/null +++ b/src/main/java/kst4contest/controller/DBController.java @@ -0,0 +1,542 @@ +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.ApplicationConstants; +import kst4contest.model.ChatMember; +import kst4contest.utils.ApplicationFileUtils; + +public class DBController { + + /** + * Name of the database file. + */ + public static final String DATABASE_FILE = "praktiKST.db"; + + /** + * Resource path for the database + */ + public static final String DATABASE_RESOURCE = "/praktiKST.db"; + + 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 = ApplicationFileUtils.getFilePath(ApplicationConstants.APPLICATION_NAME, DATABASE_FILE); + + +/* + 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 { + ApplicationFileUtils.copyResourceIfRequired( + ApplicationConstants.APPLICATION_NAME, + DATABASE_RESOURCE, + DATABASE_FILE + ); + 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.
+ * It will not insert a callsign entry, if that exists already but update + * locator, name and activity-timer. Callsign is unique and pk!
+ *
+ * Structure is like following
+ * + * "callsign" TEXT NOT NULL UNIQUE,
+ * "qra" TEXT,
+ * "name" TEXT,
+ * "lastActivityDateTime" TEXT,
+ * "worked" BOOLEAN,
+ * "worked144" BOOLEAN,
+ * "worked432" BOOLEAN,
+ * "worked1240" BOOLEAN,
+ * "worked2300" BOOLEAN,
+ * "worked3400" BOOLEAN,
+ * "worked5600" BOOLEAN,
+ * "worked10G" BOOLEAN,
+ * + * @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
+ * Usage: one time after startup, for synching the live list with the stored + * list, e.g. after program ended
+ *
+ * Structure is like following
+ * + * "callsign" TEXT NOT NULL UNIQUE,
+ * "qra" TEXT,
+ * "name" TEXT,
+ * "lastActivityDateTime" TEXT,
+ * "worked" BOOLEAN,
+ * "worked144" BOOLEAN,
+ * "worked432" BOOLEAN,
+ * "worked1240" BOOLEAN,
+ * "worked2300" BOOLEAN,
+ * "worked3400" BOOLEAN,
+ * "worked5600" BOOLEAN,
+ * "worked10G" BOOLEAN,
+ * + * @throws SQLException + */ + public HashMap fetchChatMemberWkdDataFromDB() throws SQLException { + + HashMap 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.
+ * Usage: MessagebusManagementThread, every time after a new User connects to + * the chat
+ *
+ * + * @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.
+ * Usage: User triggered after User clicked the reset-wkd button, may in each + * new contest period
+ *
+ * + * @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
+ * 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).
+ * The wkd fields should be cleaned by the user at the begin of a new + * contest
+ * + * // 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 (it´s up + * to you, guy!)!
+ *
+ * + * @return true if an entry had been modified, false if not + * + * + *
+ *
+ * Structure is like following
+ * + * "callsign" TEXT NOT NULL UNIQUE,
+ * "qra" TEXT,
+ * "name" TEXT,
+ * "lastActivityDateTime" TEXT,
+ * "worked" BOOLEAN,
+ * "worked144" BOOLEAN,
+ * "worked432" BOOLEAN,
+ * "worked1240" BOOLEAN,
+ * "worked2300" BOOLEAN,
+ * "worked3400" BOOLEAN,
+ * "worked5600" BOOLEAN,
+ * "worked10G" BOOLEAN,
+ * + * @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(); + } +} diff --git a/src/main/java/kst4contest/controller/InputReaderThread.java b/src/main/java/kst4contest/controller/InputReaderThread.java new file mode 100644 index 0000000..8d35b51 --- /dev/null +++ b/src/main/java/kst4contest/controller/InputReaderThread.java @@ -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:

+ * + * MSG|2|0|/cq DO5AMF kst4contest.test|0|

+ * + * 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(); + } + + } + + } +} diff --git a/src/main/java/kst4contest/controller/MessageBusManagementThread.java b/src/main/java/kst4contest/controller/MessageBusManagementThread.java new file mode 100644 index 0000000..64c383b --- /dev/null +++ b/src/main/java/kst4contest/controller/MessageBusManagementThread.java @@ -0,0 +1,1195 @@ +package kst4contest.controller; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.SQLException; +//import java.net.Socket; +//import java.util.ArrayList; +import java.util.Hashtable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.ObservableList; +import kst4contest.model.AirPlaneReflectionInfo; +import kst4contest.model.ChatMember; +import kst4contest.model.ChatMessage; +import kst4contest.model.ClusterMessage; + +/** + * + * This thread is responsible for processing rx and tx messages, synchronize tx + * and rx and saving the whole chat content in a textfile and write the text to + * the stdio. + * + */ +public class MessageBusManagementThread extends Thread { + + int index; + + private PrintWriter writer; +// private Socket socket; + private ChatController client; +// private File fileLogRAW; +// private TimerTask userActualizationTask; // Is used as a temporary userout-print +// private TimerTask userActualizationTask; //kst4contest.test 4 23001 + // private boolean serverReady = false; //kst4contest.test 4 23001 + private boolean serverReady = true; + private Hashtable chatMemberTable; + private final String PTRN_USERLISTENTRY = "([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}"; + private final String PTRN_QRG_CAT2 = "(([0-9]{3,4}[\\.|,| ]?[0-9]{3})([\\.|,][\\d]{1,2})?)|(([a-zA-Z][0-4]{1}[\\d]{2}\\b)([\\.|,][\\d]{1,2}\\b)?)|((\\b[0-4]{1}[\\d]{2}\\b)([\\.|,][\\d]{1,2}\\b)?)"; +// BufferedWriter bufwrtrDBGMSGOut; + +// private String text; + +// public BufferedWriter getBufwrtrDBGMSGOut() { +// return bufwrtrDBGMSGOut; +// } +// +// public void setBufwrtrDBGMSGOut(BufferedWriter bufwrtrDBGMSGOut) { +// this.bufwrtrDBGMSGOut = bufwrtrDBGMSGOut; +// } + + public boolean isServerready() { + return serverReady; + } + + public void setServerready(boolean serverReady) { + this.serverReady = serverReady; + } + + public MessageBusManagementThread(ChatController client) { + + this.client = client; + + } + + /** + * check if a chatmessage is part of the userlist via telnet 23000 port
+ * Updates userlist! + * + * @param chatMessage + */ + private void checkIfItsUserListEntry(ChatMessage messageToProcess) { + + Pattern pattern = Pattern.compile(PTRN_USERLISTENTRY); + Matcher matcher = pattern.matcher(messageToProcess.getMessageText()); + /** + * "([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}" 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); + +// this.client.getChatMemberTable().put(member.getCallSign(), member);//deleted cause change if list type + +// if (member.getName().) + +// System.out.println("Processed Userlist Entry [" + this.client.getChatMemberTable().size() + "]: Call: " +// + member.getCallSign() + ", QRA: " + member.getQra() + ", Name: " + member.getName()); + } + } + + /** + * check if a chatmessage is part of the userlist via telnet 23000 port
+ * Updates userlist! + * + * @param chatMessage + */ + private void checkIfItsUserListEntry23001(ChatMessage messageToProcess) { + + Pattern pattern = Pattern.compile(PTRN_USERLISTENTRY); + Matcher matcher = pattern.matcher(messageToProcess.getMessageText()); + /** + * "([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}" 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); + +// this.client.getChatMemberTable().put(member.getCallSign(), member); + +// if (member.getName().) + +// System.out.println("[MSGBUSMGT:] Processed Userlist Entry [" + this.client.getChatMemberTable().size() +// + "]: Call: " + member.getCallSign() + ", QRA: " + member.getQra() + ", Name: " + member.getName()); + } + } + + /** + * check if a chatmessage or a name of a chatmember contains a frequency
+ * returns String = "" if no frequency found + * + * @param chatMessage + */ + private String checkIfMessageInhibitsFrequency(ChatMessage messageToProcess) { + + Pattern pattern = Pattern.compile(PTRN_QRG_CAT2); // TODO: PTRN should depend to category-selection of own stn + Matcher matcher = pattern.matcher(messageToProcess.getMessageText()); + String[] splittedQRGString; +// splittedQRGString[0] = "0"; + + String stringAggregation = ""; + +// if (matcher.) { +// stringAggregation = ""; //reset aggregated string +// } + + while (matcher.find()) { +// System.out.println("QRG detected: "+ matcher.group() + " " + matcher.start()); + +// ChatMember member = new ChatMember(); + String matchedString = matcher.group(); + +// splittedQRGString = new String[0]; + splittedQRGString = matchedString.split(" "); + + for (int i = 0; i < splittedQRGString.length; i++) { + stringAggregation += splittedQRGString[i] + " "; + } + + System.out.println("[MSGBUSMGT:] Processed qrg info: " + stringAggregation); + +// if (member.getName().) + +// System.out.println("Processed QRG Entry [" + this.client.getChatMemberTable().size() + "]: Call: " +// + member.getCallSign() + ", QRA: " + member.getQra() + ", Name: " + member.getName()); + } + return stringAggregation; + } + + /** + * Builds UserList and gets meta informations out of the chat, as far as it is + * possible. \n This is the only place where the Chatmember-List will be written + * + * @param messageToProcess + */ + private void processRXMessage23000(ChatMessage messageToProcess) { + + String reduce; + + reduce = new String(messageToProcess.getMessageText()); + reduce = reduce.replaceAll("\\s+", " "); // reduce bursts of spaces to one space sign + + messageToProcess.setMessageText(reduce); + + if (messageToProcess.getMessageText().isEmpty()) { + System.out.println("[MSGBUSMGTT:] ######################no processable data"); + } else { + + if (reduce.length() >= 14 && reduce.length() <= 40) { + checkIfItsUserListEntry(messageToProcess); // 23001 kst4contest.test unneccessary + } + + checkIfMessageInhibitsFrequency(messageToProcess); + } + } + +// private boolean isUserInTheUserTable(String chatMemberCallsign) { +// +// String checkThisCallsign = chatMemberCallsign; +// +// if (this.client.getChatMemberTable().containsKey(checkThisCallsign)) { +// return true; +// } else +// return false; +// +// } + + /** + * 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, if not, + * returns -1. + * + * @param lookForThis + * @return Integer (index), -1 for not found + */ + private int checkListForChatMemberIndexByCallSign(ObservableList list, ChatMember lookForThis) { + + if (lookForThis == null) { + + System.out.println( + "[ChecklistForChatMemberIndexByCallsign] ERROR: null Value for Chatmember detected! Member cannot be in the list!"); + return -1; + } else if (lookForThis.getCallSign() == null) { + System.out.println( + "[ChecklistForChatMemberIndexByCallsign] ERROR: null Value in Callsign detected! Member cannot be in the list!"); + return -1; + } + /*** + * Old mechanic for index search, new one implemented due concurrentmodificationexc, which works - start + * + */ +// for (Iterator iterator = list.iterator(); iterator.hasNext();) { +// ChatMember chatMember = (ChatMember) iterator.next(); +// if (chatMember.getCallSign().equals(lookForThis.getCallSign())) { +//// System.out +//// .println("MSGBUSHELBER: Found " + chatMember.getCallSign() + " at " + list.indexOf(chatMember)); +// +// return list.indexOf(chatMember); +// } else { +// +// } +// } +// +// System.out.println("[MsgBusMgr, ERROR:] ChecklistForChatMemberIndexByCallsign, not found: " +// + lookForThis.getCallSign() + "\n "); + /*** + * Old mechanic for index search,new one implemented due concurrentmodificationexcm which works - end + * + */ + + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getCallSign().equals(lookForThis.getCallSign())) { +// System.out +// .println("MSGBUSHELBER: Found " + chatMember.getCallSign() + " at " + list.indexOf(chatMember)); + + return list.indexOf(list.get(i)); + } + } + +// for (Iterator iterator = list.iterator(); iterator.hasNext();) { +// ChatMember chatMember = (ChatMember) iterator.next(); +// System.out.println(list.indexOf(lookForThis) + ": " + chatMember.getCallSign()); +// } + + return -1; // if it´s not found, the method will always end here and return -1 + + } + + /** + * Processes received messages via port 23001 (improved telnet Interface) + * + * @param messageToProcess + * @throws IOException + * @throws SQLException + */ + private void processRXMessage23001(ChatMessage messageToProcess) throws IOException, SQLException { + + final String INITIALUSERLISTENTRY = "UA0"; + final String USERENTEREDCHAT = "UA5"; + final String USERENTEREDCHAT2 = "UA2"; // seen at 50MHZ Chat + final String initialChatHistoryEntry = "CR"; + final String SERVERMESSAGE = "CR"; + final String USERLEFTCHAT = "UR6"; + final String USERLEFTCHAT2 = "UR7"; + final String CHATCHANNELMESSAGE = "CH"; + final String REGISTREDUSERCOUNT = "UE"; + final String USERSTATECHANGE = "US4"; + final String USERLOCATORCHANGE = "LOC"; + final String USERINFOUPDATEORUSERISBACK = "UM3"; + final String DXCLUSTERMESSAGE1 = "DM"; + final String DXCLUSTERMESSAGE2 = "DL"; + final String DXCLUSTERMESSAGE3 = "MA"; + final String SRVR_DXCEND = "DF"; + final String SRVR_USERLISTEND = "UE"; + final String SRVR_COMMUNICATIONK = "CK"; + final String SRVR_LOGSTAT = "LOGSTAT"; + final String SRVR_LOGSTAT_WRONGPASSWORD = "Wrong password!"; + final String SRVR_LOGINOK = "100"; + final String SRVR_LOGINWRONGPW = "114"; + final String SRVR_LOGINWRONGEMPTYCALL = "102"; + final String SRVR_LOGINWRONGCALLSYNTAX = "103"; + final String SRVR_LOGINWRONGCALLUNKNOWN = "101"; + + if (messageToProcess.getMessageText().isEmpty()) { + System.out.println("[MSGBUSMGTT:] ######################no processable data"); + + } else { + + if (messageToProcess.getMessageText().contains(SRVR_LOGSTAT)) { + String logstatMessage[]; + logstatMessage = messageToProcess.getMessageText().split("\\|"); + if (logstatMessage[1].contains(SRVR_LOGINOK)) { + this.client.setConnectedAndLoggedIn(true); + } else { + this.client.setConnectedAndNOTLoggedIn(true); + this.client.setConnectedAndLoggedIn(false); + } + } + + String splittedMessageLine[] = messageToProcess.getMessageText().split("\\|"); + + /** + * Initializes the Userlist if entry fits UA0 + */ + if (splittedMessageLine[0].contains(INITIALUSERLISTENTRY)) { +// System.out.println("MSGBUS: User detected"); + + ChatMember newMember = new ChatMember(); + + newMember.setAirPlaneReflectInfo(new AirPlaneReflectionInfo()); // TODO: Only bugfix, check + + newMember.setCallSign(splittedMessageLine[2]); + newMember.setName(splittedMessageLine[3]); + newMember.setQra(splittedMessageLine[4]); + newMember.setState(Integer.parseInt(splittedMessageLine[5])); + newMember.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat()); + +// this.client.getChatMemberTable().put(splittedMessageLine[2], newMember); //TODO: map -> List + + this.client.getLst_chatMemberList().add(newMember); + + this.client.getDbHandler().storeChatMember(newMember); + +// bufwrtrDBGMSGOut.write(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() +// + "[MSGBUSMGT:] User detected and added to list [" + this.client.getChatMemberTable().size() +// + "] :" + newMember.getCallSign() + "\n"); +// bufwrtrDBGMSGOut.flush(); +// System.out.println("[MSGBUSMGT:] User detected and added to list [" +// + this.client.getChatMemberTable().size() + "] :" + newMember.getCallSign()); + } else + + /** + * Actualize Userlist, add new entry UA5 or UA2 + */ + if (splittedMessageLine[0].contains(USERENTEREDCHAT) || splittedMessageLine[0].contains(USERENTEREDCHAT2)) { +// System.out.println("MSGBUS: User detected"); + + ChatMember newMember = new ChatMember(); + + newMember.setAirPlaneReflectInfo(new AirPlaneReflectionInfo()); + newMember.setCallSign(splittedMessageLine[2]); + newMember.setName(splittedMessageLine[3]); + newMember.setQra(splittedMessageLine[4]); + newMember.setState(Integer.parseInt(splittedMessageLine[5])); + newMember.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat()); + + newMember = this.client.getDbHandler().fetchChatMemberWkdDataForOnlyOneCallsignFromDB(newMember); + + this.client.getLst_chatMemberList().add(newMember); + + this.client.getDbHandler().storeChatMember(newMember); + +// this.client.getChatMemberTable().put(splittedMessageLine[2], newMember); + +// System.out.println("[MSGBUSMGT:] New entered User detected and added to list [" +// + this.client.getChatMemberTable().size() + "] :" + newMember.getCallSign()); + } else + + /** + * Actualize Userlist, remove entry UR6, UR7 + */ + if (splittedMessageLine[0].contains(USERLEFTCHAT) || splittedMessageLine[0].contains(USERLEFTCHAT2)) { +// System.out.println("MSGBUS: User detected"); + + ChatMember newMember = new ChatMember(); + + newMember.setCallSign(splittedMessageLine[2]); + +// this.client.getChatMemberTable().remove(newMember.getCallSign()); + + System.out.println("[MSGBUSMGT, Info:] User left Chat and will be removed from list [" + + this.client.getLst_chatMemberList().size() + "] :" + newMember.getCallSign()); + try { + this.client.getLst_chatMemberList().remove( + checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), newMember)); + + } catch (Exception e) { + System.out.println("[MSGBUSMGT, EXC!, Error:] User sent left chat but had not been there ... [" + + this.client.getLst_chatMemberList().size() + "] :" + newMember.getCallSign() + "\n" + + e.getStackTrace()); +// e.printStackTrace(); + } + +// int indexToDelete = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), +// newMember); +// if (indexToDelete != -1) { +// System.out.println("[MSGBUSMGT:] User left Chat and is removed from list [" +// + this.client.getLst_chatMemberList().size() + "] :" + newMember.getCallSign()); +// +// this.client.getLst_chatMemberList().remove(indexToDelete); +// +// } else { +// System.out.println("[MSGBUSMGT:] Error, user sent left chat but had not been there ... [" +// + this.client.getLst_chatMemberList().size() + "] :" + newMember.getCallSign()); +// +// } + + } else + + /** + * Chatmessage dm5m to do5amf CH|2|1663966534|DM5M|dm5m-team|0|kst4contest.test|DO5AMF| + * + * CH|2|1663966535|DM5M|dm5m-team|0|kst4contest.test|0| + */ + if (splittedMessageLine[0].contains(CHATCHANNELMESSAGE)) { +// System.out.println("MSGBUS: User detected"); + + ChatMessage newMessage = new ChatMessage(); + newMessage.setChatCategory(this.client.getCategory()); + newMessage.setMessageGeneratedTime(splittedMessageLine[2]); // TODO: insert readable time? + + if (splittedMessageLine[3].equals("SERVER")) { + ChatMember dummy = new ChatMember(); + dummy.setCallSign("SERVER"); + dummy.setName("Sysop"); + newMessage.setSender(dummy); + } else { + + ChatMember temp = new ChatMember(); + temp.setCallSign(splittedMessageLine[3]); + + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), temp); + + if (index != -1) { + + newMessage.setSender(this.client.getLst_chatMemberList().get(index)); // set sender to member of + // b4 init list + } else { + + if (!temp.getCallSign().equals(this.client.getChatPreferences().getLoginCallSign().toUpperCase())) { + temp.setCallSign("[n/a]" + temp.getCallSign()); + } + + newMessage.setSender(temp); // if someone sent a message without being in the userlist (cause + // on4kst missed implementing....) + } + +// newMessage.setSender(this.client.getChatMemberTable().get(splittedMessageLine[3])); + } + + newMessage.setMessageSenderName(splittedMessageLine[4]); + newMessage.setMessageText(splittedMessageLine[6]); + + if (splittedMessageLine[7].equals("0")) { + // message is not directed to anyone + ChatMember dummy = new ChatMember(); + dummy.setCallSign("ALL"); + newMessage.setReceiver(dummy); + + this.client.getLst_toAllMessageList().add(0, newMessage); // sdtout to all message-List + + } else { + + ChatMember temp2 = new ChatMember(); + temp2.setCallSign(splittedMessageLine[7]); + + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), temp2); + + if (index != -1) { + newMessage.setReceiver(this.client.getLst_chatMemberList().get(index));// -1: Member left Chat + // before... + } else { + temp2.setCallSign(temp2.getCallSign() + "(left)"); + newMessage.setReceiver(temp2); + } + + System.out.println("message directed to: " + newMessage.getReceiver().getCallSign() + ". EQ?: " + this.client.getownChatMemberObject().getCallSign() + " sent by: " + newMessage.getSender().getCallSign().toUpperCase() + " -> EQ?: "+ this.client.getChatPreferences().getLoginCallSign().toUpperCase()); + + if (newMessage.getReceiver().getCallSign() + .equals(this.client.getChatPreferences().getLoginCallSign())) { + + this.client.getLst_toMeMessageList().add(0, newMessage); + + System.out.println("message directed to me: " + newMessage.getReceiver().getCallSign() + "."); + + } else if (newMessage.getSender().getCallSign().toUpperCase() // if you sent the message, it will be sorted in to + // the "to you message list" + .equals(this.client.getChatPreferences().getLoginCallSign().toUpperCase())) { + String originalMessage = newMessage.getMessageText(); + newMessage + .setMessageText("(>" + newMessage.getReceiver().getCallSign() + ")" + originalMessage); + this.client.getLst_toMeMessageList().add(0, newMessage); // TODO:check + + } else { + this.client.getLst_toOtherMessageList().add(0, newMessage); + +// System.out.println("MSGBS bgfx: tx call = " + newMessage.getSender().getCallSign() + " / rx call = " + newMessage.getReceiver().getCallSign()); + } + + // sdtout to me message-List + +// newMessage.setReceiver(this.client.getChatMemberTable().get(splittedMessageLine[7])); // set sender + // to the + // member of + // before + // initialized + // list + } + +// System.out.println("[MSGBUSMGT:] processed message: " + newMessage.getChatCategory().getCategoryNumber() +// + " " + newMessage.getSender().getCallSign() + ", " + newMessage.getMessageSenderName() + " -> " +// + newMessage.getReceiver().getCallSign() + ": " + newMessage.getMessageText()); + + String locatedFrequencies = checkIfMessageInhibitsFrequency(newMessage); + + SimpleStringProperty qrg = new SimpleStringProperty(locatedFrequencies); + + if (!splittedMessageLine[3].equals("SERVER")) { + + if (locatedFrequencies.equals("")) { + // no qrg found, nothing to do + } else { + +// String stringAggregation = ""; +// +// for (int i = 0; i < locatedFrequencies.length; i++) { +// stringAggregation += locatedFrequencies[i] + " "; +// } + + ChatMember temp3 = new ChatMember(); + temp3.setCallSign(splittedMessageLine[3]); + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), temp3); + + if (index == -1) { // user is not in the userlist but sent message... + + /** + * CH|2|1664663240|IK7LMX|Gilberto QRO|0|pse ant to jn80|YT5W| Caused this line + */ + System.out.println("[MSGBUSMGT:] ERROR, Frequency for " + splittedMessageLine[3] + + " is not settable, Callsign is not in the Member-list!"); + + ChatMember newMember = new ChatMember(); + newMember.setCallSign(splittedMessageLine[3]); + newMember.setName(splittedMessageLine[4]); + newMember.setFrequency(qrg); +// newMember.setFrequency(locatedFrequencies); +// this.client.getLst_chatMemberList().add(newMember); + + } else { + /** + * User is in the list... + * + */ + this.client.getLst_chatMemberList().get(index).setFrequency(qrg); + System.out.println("[MSGBUSMGT:] Frequency for " + splittedMessageLine[3] + " setted: " + + locatedFrequencies); + +// this.client.getLst_chatMemberList(). + +// ChatMember dummy = new ChatMember(); +// +// dummy.setAirPlaneReflectInfo(new AirPlaneReflectionInfo()); //TODO: check if this is neccessary +// this.client.getLst_chatMemberList().add(dummy); // TODO: Bugfix for UI actualization, maybe we dont need that any more +// this.client.getLst_chatMemberList().remove(dummy); +// this.client.getLst_chatMemberList().sorted(); + +// + } + } + } + + // TODO: Next: get frequency infos out of name? + } else + + /** + * LOC|1664012560|I4GHG/6|JN63DT| Actualize singleton Userlist, changes locator + * of existing user or add him with this locator + */ + if (splittedMessageLine[0].contains(USERLOCATORCHANGE)) { +// System.out.println("MSGBUS: User detected"); + + ChatMember temp4 = new ChatMember(); + temp4.setCallSign(splittedMessageLine[2]); + temp4.setQra(splittedMessageLine[3]); + temp4.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat()); + + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), temp4); + + if (index != -1) { + + System.out.println("[MSGBUSMGT:] Locator Change of [" + (splittedMessageLine[2] + "], old was: " + + this.client.getLst_chatMemberList().get(index).getQra() + " new is: " + + splittedMessageLine[3])); + + this.client.getLst_chatMemberList().get(index).setQra(splittedMessageLine[3]); + + } else { + System.out.println("[MSGBUSMGT:] ERROR! Locator Change of [" + + (splittedMessageLine[2] + "] is not possible, user is not in the Table!")); + +// ChatMember newMember = new ChatMember(); +// newMember.setCallSign(splittedMessageLine[2]); +// newMember.setQra(splittedMessageLine[3]); +// this.client.getChatMemberTable().put(newMember.getCallSign(), newMember); + +// this.client.getLst_chatMemberList().add(temp4); + } + + this.client.getDbHandler().storeChatMember(temp4); // TODO thats a bit unclean, its less an insert but a + // locator update + + } else + + /** + * DX-Cluster-Message type 1 + * DM|0|1664050013|2006|w4cwf|144118.0|PA2CHR|EM85WH<>JO22 hrd + * -21db|EM85WH|JO32DB| + */ + if (splittedMessageLine[0].contains(DXCLUSTERMESSAGE1)) { +// System.out.println("MSGBUS: User detected"); + + ClusterMessage dxcMsg = new ClusterMessage(); + + dxcMsg.setTimeGenerated(splittedMessageLine[2]); + + ChatMember newDXCListSender = new ChatMember(); + newDXCListSender.setCallSign(splittedMessageLine[4]); + newDXCListSender.setQra(splittedMessageLine[8]); + + ChatMember newDXCListReceiver = new ChatMember(); + newDXCListReceiver.setFrequency(new SimpleStringProperty(splittedMessageLine[5])); + newDXCListReceiver.setCallSign(splittedMessageLine[6]); + newDXCListReceiver.setQra(splittedMessageLine[9]); + + dxcMsg.setSender(newDXCListSender); + dxcMsg.setReceiver(newDXCListReceiver); + + dxcMsg.setMessageInhibited(splittedMessageLine[7]); + dxcMsg.setQrgSpotted(splittedMessageLine[5]); + + this.client.getLst_clusterMemberList().add(0, dxcMsg); + +// System.out.println("[MSGBUSMGT:] DXCluster Message detected "); + +// if (!this.client.getdXClusterMemberTable().contains(splittedMessageLine[6])) { +// this.client.getdXClusterMemberTable().put(newDXCListMember.getCallSign(), newDXCListMember); +// } + + } else + + /** + * DX-Cluster-Message type 2
+ * DL|1664047594|1926|dg9yih|144000.0|DL6BF|JO32PC + * + * JO32QI zerstoert qso|JO32PC|JO32QI| -> Clustermessage + * DL|1664048232|1937|pu2pyb|144500.0|PU2NEZ|FM| | | + */ + if (splittedMessageLine[0].contains(DXCLUSTERMESSAGE2)) { +// System.out.println("MSGBUS: User detected"); + + ClusterMessage dxcMsg2 = new ClusterMessage(); + + dxcMsg2.setTimeGenerated(splittedMessageLine[1]); + + ChatMember newDXCListSender2 = new ChatMember(); + newDXCListSender2.setCallSign(splittedMessageLine[3]); + newDXCListSender2.setQra(splittedMessageLine[7]); + + ChatMember newDXCListReceiver2 = new ChatMember(); + newDXCListReceiver2.setFrequency(new SimpleStringProperty(splittedMessageLine[4])); + newDXCListReceiver2.setCallSign(splittedMessageLine[5]); + newDXCListReceiver2.setQra(splittedMessageLine[8]); + + dxcMsg2.setSender(newDXCListSender2); + dxcMsg2.setReceiver(newDXCListReceiver2); + + dxcMsg2.setMessageInhibited(splittedMessageLine[6]); + dxcMsg2.setQrgSpotted(splittedMessageLine[4]); + + this.client.getLst_clusterMemberList().add(0, dxcMsg2); + + } else + + /** + * DX-Cluster-Message type 3
+ * MA|0|1687204743|e77ar|OK2AF|JN94AS|JN89AR| + */ + if (splittedMessageLine[0].contains(DXCLUSTERMESSAGE3)) { +// System.out.println("MSGBUS: User detected"); + + ClusterMessage dxcMsg3 = new ClusterMessage(); + + dxcMsg3.setTimeGenerated(splittedMessageLine[2]); + + ChatMember newDXCListSender3 = new ChatMember(); + newDXCListSender3.setCallSign(splittedMessageLine[3]); + newDXCListSender3.setQra(splittedMessageLine[5]); + + ChatMember newDXCListReceiver3 = new ChatMember(); +// newDXCListReceiver3.setFrequency(splittedMessageLine[4]); + newDXCListReceiver3.setCallSign(splittedMessageLine[4]); + newDXCListReceiver3.setQra(splittedMessageLine[5]); + + dxcMsg3.setSender(newDXCListSender3); + dxcMsg3.setReceiver(newDXCListReceiver3); + + dxcMsg3.setMessageInhibited(""); + dxcMsg3.setQrgSpotted(""); + + this.client.getLst_clusterMemberList().add(0, dxcMsg3); + + } else + + /** + * Userstatechange:, last digit 0 = in chat, 1 away, 2 here, 3 also away... + * US4|2|DM5M|0| + */ + if (splittedMessageLine[0].contains(USERSTATECHANGE)) { +// System.out.println("MSGBUS: User detected"); + + ChatMember stateChangeMember = new ChatMember(); + + stateChangeMember.setCallSign(splittedMessageLine[2]); + stateChangeMember.setState(Integer.parseInt(splittedMessageLine[3])); + +// System.out.println("[MSGBUSMGT:] DXCluster Message detected "); + + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), + stateChangeMember); + + if (index != -1 && index != 0) { + this.client.getLst_chatMemberList().get(index).setState(stateChangeMember.getState()); + } + +// this.client.getChatMemberTable().get(stateChangeMember.getCallSign()) +// .setState(stateChangeMember.getState()); + + } else + + /** + * Userinfo-update: UM3|2|HA4XN|Zoli 2m SSB/CW|JN96LX|2| + */ + if (splittedMessageLine[0].contains(USERINFOUPDATEORUSERISBACK)) { + + ChatMember stateChangeMember = new ChatMember(); + + stateChangeMember.setCallSign(splittedMessageLine[2]); + stateChangeMember.setName(splittedMessageLine[3]); + stateChangeMember.setQra(splittedMessageLine[4]); + stateChangeMember.setState(Integer.parseInt(splittedMessageLine[5])); + stateChangeMember.setLastActivity(new Utils4KST().time_generateActualTimeInDateFormat()); + + this.client.getDbHandler().storeChatMember(stateChangeMember); // TODO: not clean, it should be an + // upodate + +// System.out.println("[MSGBUSMGT:] DXCluster Message detected "); + + int index = checkListForChatMemberIndexByCallSign(this.client.getLst_chatMemberList(), + stateChangeMember); + + this.client.getLst_chatMemberList().get(index).setName(stateChangeMember.getName()); + this.client.getLst_chatMemberList().get(index).setQra(stateChangeMember.getQra()); + this.client.getLst_chatMemberList().get(index).setState(stateChangeMember.getState()); + +// this.client.getChatMemberTable().get(stateChangeMember.getCallSign()) +// .setName(stateChangeMember.getName()); +// this.client.getChatMemberTable().get(stateChangeMember.getCallSign()) +// .setQra(stateChangeMember.getQra()); +// this.client.getChatMemberTable().get(stateChangeMember.getCallSign()) +// .setState(stateChangeMember.getState()); + + } else + + /** + * Userinfo-update: UE|2|22562| + */ + if (splittedMessageLine[0].contains(SRVR_USERLISTEND)) { + + // No worthy information, count of users + } else + + if (splittedMessageLine[0].contains(SRVR_DXCEND)) { + + // No worthy information, count of users + } else + + if (splittedMessageLine[0].contains(SRVR_COMMUNICATIONK)) { + // No worthy information, end of srvrmsgs + } else + + //-> LOGSTAT|114|Wrong password!| + if (splittedMessageLine[0].contains(SRVR_LOGSTAT) && splittedMessageLine.length <= 5) { + System.out.println("Passwort falsch!"); + + if (splittedMessageLine[2].contains("password")) { + splittedMessageLine[2] += "pse disc- and reconnect"; + } + + ChatMember server = new ChatMember(); + server.setCallSign("SERVER"); + server.setName("SERVER"); + + ChatMessage pwErrorMsg = new ChatMessage(); + + pwErrorMsg.setMessageGeneratedTime(client.getCurrentEpochTime()+""); + pwErrorMsg.setSender(server); + pwErrorMsg.setMessageText(splittedMessageLine[2]); + + for (int i = 0; i < 10; i++) { + client.getLst_toMeMessageList().add(pwErrorMsg); + client.getLst_toAllMessageList().add(pwErrorMsg); + } + +// this.client.disconnect(); + } + + else { + +// bufwrtrDBGMSGOut.write(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() +// + "[MSGBUSMGT:] Critical, detected unhandled Chatmessage -> " +// + messageToProcess.getMessageText() + "\n"); +// bufwrtrDBGMSGOut.flush(); + + System.out.print(new Utils4KST().time_generateCurrentMMDDhhmmTimeString() + + " [MSGBUSMGT:] Critical, detected unhandled Chatmessage -> " + + messageToProcess.getMessageText() + "\n"); + + } + + // ******************************************************************QUICKNDIRTY........ +// ChatMember thisMemberActualizesUserListForRefreshingIntheGuy = new ChatMember(); +// thisMemberActualizesUserListForRefreshingIntheGuy.setCallSign("REFR"); +// thisMemberActualizesUserListForRefreshingIntheGuy.setAirPlaneReflectInfo(new AirPlaneReflectionInfo()); +// this.client.getLst_chatMemberList().add(thisMemberActualizesUserListForRefreshingIntheGuy); +// this.client.getLst_chatMemberList().isEmpty(); +// System.out.println("MSGBUS BGFX Listactualizer"); +// this.client.getLst_chatMemberList().remove(thisMemberActualizesUserListForRefreshingIntheGuy); + // ******************************************************************QUICKNDIRTY........ + +// checkIfMessageInhibitsFrequency(messageToProcess); + } + } + + @Override + public void interrupt() { + super.interrupt(); + + } + + + public void run() { + +// fileLogRAW = new File(new Utils4KST().time_generateCurrentMMddString() + "_praktiKST_raw.txt"); + +// FileWriter fileWriterRAWChatMSGOut = null; +// BufferedWriter bufwrtrRawMSGOut; + +// try { +// fileWriterRAWChatMSGOut = new FileWriter(fileLogRAW, true); +// +// } catch (IOException e1) { +// // TODO Auto-generated catch block +// e1.printStackTrace(); +// } + +// bufwrtrRawMSGOut = new BufferedWriter(fileWriterRAWChatMSGOut); + +// File fileLogClientOut = new File(new Utils4KST().time_generateCurrentMMddString() + "_praktiKST_out.txt"); + +// FileWriter fileWriterOutChatMSGOut = null; +// +// try { +// fileWriterOutChatMSGOut = new FileWriter(fileLogClientOut, true); +// } catch (IOException e2) { +// // TODO Auto-generated catch block +// e2.printStackTrace(); +// } +// +// try { +// fileWriterRAWChatMSGOut = new FileWriter(fileLogClientOut, true); +// +// } catch (IOException e1) { +// // TODO Auto-generated catch block +// e1.printStackTrace(); +// try { +// fileWriterRAWChatMSGOut.close(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } + +// bufwrtrDBGMSGOut = new BufferedWriter(fileWriterOutChatMSGOut); + +// new Timer().schedule(new UserActualizationTask(client), 4000, 60000);// TODO: Temporary userlistoutput with +// // known qrgs +// +// userActualizationTask = new UserActualizationTask(client); // kst4contest.test 4 23001 +// userActualizationTask.run();// kst4contest.test 4 23001 + + ChatMessage messageTextRaw = new ChatMessage(); // moved out of the while + String messageLine; + + while (true) { + + + + try { + messageTextRaw = client.getMessageRXBus().take(); + + if (messageTextRaw.getMessageText().equals("POISONPILL_KILLTHREAD") && messageTextRaw.getMessageSenderName().equals("POISONPILL_KILLTHREAD")) { + client.getMessageRXBus().clear(); + break; + } + else { + messageLine = messageTextRaw.getMessageText(); + + /*********************************************** + * CASE RX + ***********************************************/ + +// if (client.getMessageRXBus().peek() != null) { + +// try { +// messageTextRaw = client.getMessageRXBus().take(); + // +//// System.out.println("MSBGBUS: rxed: " + messageTextRaw); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + + if (messageTextRaw.getMessageText() == null) { + System.out.println("[MSGBUSMGT:] ERROR! got NULL message! BYE!"); +// this.interrupt(); +// break; + } + + messageLine = messageTextRaw.getMessageText(); + +// try { +// bufwrtrRawMSGOut.write(messageLine + "\n"); +// bufwrtrRawMSGOut.flush(); + // +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + + System.out.println(messageTextRaw.getMessageText() + " <- RXed"); // Stdout at + // Console#######################################################TODO:Wichtig + + try { + processRXMessage23001(messageTextRaw); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + } catch (InterruptedException e1) { + this.interrupt(); + // TODO Auto-generated catch block + e1.printStackTrace(); + // client.getMessageRXBus().clear(); + } + { +// System.out.println("MessagebusmgtThread: Readthread is interrupted! Queue will be resetted"); +// this.interrupt(); +// client.getMessageRXBus().clear(); + } + +// if (client.getMessageRXBus().peek() == null) { +// +// Timer doNothingTimer = new Timer(); +// doNothingTimer.schedule(new TimerTask() { +// +// @Override +// public void run() { +// +// //do nothing +// +// } +// }, 100);// TODO: Temporary +// } +// +// +// if (client.getMessageRXBus().peek() == null && client.getMessageTXBus().peek() == null) { +// +// if (this.client.isDisconnectionPerformedByUser()) { +// break;//TODO: what if it´s not the finally closage but a band channel change? +// } +// // do nothing +//// try { +//// this.sleep(20); +//// } catch (InterruptedException e) { +//// // TODO Auto-generated catch block +//// e.printStackTrace(); +//// } catch (Exception e2) { +//// // TODO Auto-generated catch block +//// e2.printStackTrace(); +//// } +// } +// else + { + +// messageLine = messageTextRaw.getMessageText(); +// +// /*********************************************** +// * CASE RX +// ***********************************************/ +// +//// if (client.getMessageRXBus().peek() != null) { +// +//// try { +//// messageTextRaw = client.getMessageRXBus().take(); +//// +////// System.out.println("MSBGBUS: rxed: " + messageTextRaw); +//// } catch (InterruptedException e) { +//// // TODO Auto-generated catch block +//// e.printStackTrace(); +//// } +// +// if (messageTextRaw.getMessageText() == null) { +// System.out.println("[MSGBUSMGT:] ERROR! got NULL message! BYE!"); +//// this.interrupt(); +//// break; +// } +// +// messageLine = messageTextRaw.getMessageText(); +// +//// try { +//// bufwrtrRawMSGOut.write(messageLine + "\n"); +//// bufwrtrRawMSGOut.flush(); +//// +//// } catch (IOException e) { +//// // TODO Auto-generated catch block +//// e.printStackTrace(); +//// } +// +// System.out.println(messageTextRaw.getMessageText() + " <- RXed"); // Stdout at +// // Console#######################################################TODO:Wichtig +// +// try { +// processRXMessage23001(messageTextRaw); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (SQLException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + +// } //end peek != null + + /************************************************************** + * End of case RX + **************************************************************/ + + /************************************************************** + * Start of case TX + **************************************************************/ + +// if (client.getMessageTXBus().peek() != null) { +// /*********************************************** +// * CASE TX +// ***********************************************/ +// +// if (this.isServerready()) { +// // then send the line +// +// try { +// messageTextRaw = client.getMessageTXBus().take(); +//// this.setServerready(false); // after tx always wait for an answer prompt //23000 +// this.setServerready(true); +// +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// +// 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 { +// client.getWriteThread().tx(messageTextRaw); +// System.out.println("BUS: tx: " + messageTextRaw.getMessageText()); +// +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// +// //////////////////////// bgfx ab here////////////////////////////// +//// try { +//// bufwrtrRawMSGOut.write(messageLine + "\r"); +////// bw.write(messageLine + "\n");//kst4contest.test 4 23001 +//// bufwrtrRawMSGOut.flush(); +//// +//// } catch (IOException 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 { +// client.getWriteThread().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(); +// } +// } +// +// } else { +//// System.out.println("msgbus no elements yet"); +// } +// } //end tx.peek != null + } + +// System.out.println("messagebusmgt while performed"); + + } // while true end + System.out.println("Msgbusmgt: interrupt"); + this.interrupt(); + } +} diff --git a/src/main/java/kst4contest/controller/ReadThread.java b/src/main/java/kst4contest/controller/ReadThread.java new file mode 100644 index 0000000..a3d35a5 --- /dev/null +++ b/src/main/java/kst4contest/controller/ReadThread.java @@ -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; + } + + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/controller/ReadUDPbyAirScoutMessageThread.java b/src/main/java/kst4contest/controller/ReadUDPbyAirScoutMessageThread.java new file mode 100644 index 0000000..53ea3e0 --- /dev/null +++ b/src/main/java/kst4contest/controller/ReadUDPbyAirScoutMessageThread.java @@ -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 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; + } + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/controller/ReadUDPbyUCXMessageThread.java b/src/main/java/kst4contest/controller/ReadUDPbyUCXMessageThread.java new file mode 100644 index 0000000..36f7dee --- /dev/null +++ b/src/main/java/kst4contest/controller/ReadUDPbyUCXMessageThread.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/controller/RegexTester.java b/src/main/java/kst4contest/controller/RegexTester.java new file mode 100644 index 0000000..7cd6c55 --- /dev/null +++ b/src/main/java/kst4contest/controller/RegexTester.java @@ -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()); + } + } + +} diff --git a/src/main/java/kst4contest/controller/StartChat.java b/src/main/java/kst4contest/controller/StartChat.java new file mode 100644 index 0000000..4693705 --- /dev/null +++ b/src/main/java/kst4contest/controller/StartChat.java @@ -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(); + + } + +} diff --git a/src/main/java/kst4contest/controller/UCXLogFileToHashsetParser.java b/src/main/java/kst4contest/controller/UCXLogFileToHashsetParser.java new file mode 100644 index 0000000..c8a97c8 --- /dev/null +++ b/src/main/java/kst4contest/controller/UCXLogFileToHashsetParser.java @@ -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
+ * returns ChatMember = null, if no frequency found + * + * @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 parse() throws IOException { + + HashMap 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; + + } + +} diff --git a/src/main/java/kst4contest/controller/UserActualizationTask.java b/src/main/java/kst4contest/controller/UserActualizationTask.java new file mode 100644 index 0000000..e4dbf89 --- /dev/null +++ b/src/main/java/kst4contest/controller/UserActualizationTask.java @@ -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 fetchedWorkedSet = new HashMap<>(); +// HashMap 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 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 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 fetchedWorkedMap = new HashMap<>(); +// +// fetchedWorkedMap = this.client.getMap_ucxLogInfoWorkedCalls(); + +// ObservableList 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 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 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 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 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 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 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 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 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(); +// } + } + +} diff --git a/src/main/java/kst4contest/controller/Utils4KST.java b/src/main/java/kst4contest/controller/Utils4KST.java new file mode 100644 index 0000000..65d5eeb --- /dev/null +++ b/src/main/java/kst4contest/controller/Utils4KST.java @@ -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; + + } + +} diff --git a/src/main/java/kst4contest/controller/WriteThread.java b/src/main/java/kst4contest/controller/WriteThread.java new file mode 100644 index 0000000..957bb22 --- /dev/null +++ b/src/main/java/kst4contest/controller/WriteThread.java @@ -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) { +// +// } + + } +} diff --git a/src/main/java/kst4contest/controller/keepAliveMessageSenderTask.java b/src/main/java/kst4contest/controller/keepAliveMessageSenderTask.java new file mode 100644 index 0000000..974e92d --- /dev/null +++ b/src/main/java/kst4contest/controller/keepAliveMessageSenderTask.java @@ -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); + } + +} diff --git a/src/main/java/kst4contest/locatorUtils/Angle.java b/src/main/java/kst4contest/locatorUtils/Angle.java new file mode 100644 index 0000000..f2b5fa2 --- /dev/null +++ b/src/main/java/kst4contest/locatorUtils/Angle.java @@ -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 + * + */ +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); + } +} \ No newline at end of file diff --git a/src/main/java/kst4contest/locatorUtils/Latitude.java b/src/main/java/kst4contest/locatorUtils/Latitude.java new file mode 100644 index 0000000..b21ec60 --- /dev/null +++ b/src/main/java/kst4contest/locatorUtils/Latitude.java @@ -0,0 +1,48 @@ +package kst4contest.locatorUtils; + +import java.math.BigDecimal; +import java.math.MathContext; + +/** + * Latitude. + * + * @author Paul Picazo + * + */ +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; + } + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/locatorUtils/Location.java b/src/main/java/kst4contest/locatorUtils/Location.java new file mode 100644 index 0000000..6903c55 --- /dev/null +++ b/src/main/java/kst4contest/locatorUtils/Location.java @@ -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 + * + */ +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; + } +} diff --git a/src/main/java/kst4contest/locatorUtils/Longitude.java b/src/main/java/kst4contest/locatorUtils/Longitude.java new file mode 100644 index 0000000..8bf2778 --- /dev/null +++ b/src/main/java/kst4contest/locatorUtils/Longitude.java @@ -0,0 +1,49 @@ +package kst4contest.locatorUtils; + +import java.math.BigDecimal; +import java.math.MathContext; + +/** + * Longitude. + * + * @author Paul Picazo + * + */ +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; + } + + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/model/AirPlane.java b/src/main/java/kst4contest/model/AirPlane.java new file mode 100644 index 0000000..2aeed03 --- /dev/null +++ b/src/main/java/kst4contest/model/AirPlane.java @@ -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; + } + +} diff --git a/src/main/java/kst4contest/model/AirPlaneReflectionInfo.java b/src/main/java/kst4contest/model/AirPlaneReflectionInfo.java new file mode 100644 index 0000000..fbb7538 --- /dev/null +++ b/src/main/java/kst4contest/model/AirPlaneReflectionInfo.java @@ -0,0 +1,62 @@ +package kst4contest.model; + +import javafx.collections.ObservableList; + +public class AirPlaneReflectionInfo { + + String date; + ChatMember sender, receiver; + int airPlanesReachableCntr; + ObservableList 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 getRisingAirplanes() { + return risingAirplanes; + } + + public void setRisingAirplanes(ObservableList 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; + } + +} diff --git a/src/main/java/kst4contest/model/ChatCategory.java b/src/main/java/kst4contest/model/ChatCategory.java new file mode 100644 index 0000000..85630ac --- /dev/null +++ b/src/main/java/kst4contest/model/ChatCategory.java @@ -0,0 +1,290 @@ +package kst4contest.model; + +/* 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 +*
+* 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):
+ * "pse listen at .325"
+ *
+ * + * 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
+ * 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):
+ * "pse listen at .325"
+ *
+ * + * 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
+ * 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"; + } + + }; + +} diff --git a/src/main/java/kst4contest/model/ChatMember.java b/src/main/java/kst4contest/model/ChatMember.java new file mode 100644 index 0000000..e36e18a --- /dev/null +++ b/src/main/java/kst4contest/model/ChatMember.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/main/java/kst4contest/model/ChatMessage.java b/src/main/java/kst4contest/model/ChatMessage.java new file mode 100644 index 0000000..4760e3c --- /dev/null +++ b/src/main/java/kst4contest/model/ChatMessage.java @@ -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; + } + + + +} diff --git a/src/main/java/kst4contest/model/ChatPreferences.java b/src/main/java/kst4contest/model/ChatPreferences.java new file mode 100644 index 0000000..80fa711 --- /dev/null +++ b/src/main/java/kst4contest/model/ChatPreferences.java @@ -0,0 +1,1169 @@ +package kst4contest.model; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import kst4contest.ApplicationConstants; +import kst4contest.utils.ApplicationFileUtils; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +public class ChatPreferences { + + /** + * Name of file to store preferences in. + */ + public static final String PREFERENCES_FILE = "preferences.xml"; + + /** + * Resource with the example properties xml file. + */ + public static final String PREFERENCE_RESOURCE = "/praktiKSTpreferences.xml"; + + /** + * Default constructor will set the default values (also for predefined texts + * and shorts) automatically at initialization + * + * TODO: delete this from the kst4contest.view/Main.java! + */ + public ChatPreferences() { + ApplicationFileUtils.copyResourceIfRequired(ApplicationConstants.APPLICATION_NAME, PREFERENCE_RESOURCE, PREFERENCES_FILE); + +// shortcuts[2] = "pse"; +// shortcuts[3] = "turn"; +// shortcuts[4] = "ant"; +// shortcuts[5] = "my"; +// shortcuts[6] = "dir"; +// shortcuts[7] = "sked"; +// shortcuts[8] = "ssb"; +// shortcuts[9] = "cw"; +// shortcuts[10] = "try"; +// shortcuts[11] = "agn"; +// shortcuts[12] = "nw"; +// shortcuts[13] = "qrg"; +// shortcuts[14] = "beaming"; +// shortcuts[15] = "calling"; +// shortcuts[16] = "lsn to"; +// shortcuts[17] = "qsb"; +// shortcuts[18] = "rpt"; +// shortcuts[19] = "nr"; +// shortcuts[20] = "ur"; +// shortcuts[21] = "I"; +// shortcuts[22] = "hear"; +// shortcuts[23] = "you"; +// shortcuts[24] = "weak"; +// shortcuts[25] = "nil, sry"; +// shortcuts[26] = "maybe"; +// shortcuts[27] = "later"; +// shortcuts[28] = "tmw"; +// shortcuts[29] = "rrr"; +// shortcuts[30] = "tnx"; +// shortcuts[31] = "qso"; +// shortcuts[32] = "73"; +// shortcuts[33] = "?"; +// shortcuts[34] = "!"; +// shortcuts[35] = ","; +// shortcuts[36] = "MYQRG"; +// +// textSnippets[0] = "Hi OM, try sked?"; +// textSnippets[1] = "I am calling cq ur dir, pse lsn to me at "; +// textSnippets[2] = "pse ur qrg?"; +// textSnippets[3] = "rrr, I move to your qrg nw, pse ant dir me"; +// textSnippets[4] = "Hrd you but many qrm here, pse agn"; +// +// textSnippets[5] = "I turn my ant to you"; +// +// textSnippets[6] = "Sry, strong qrm by local station there, may try "; +// textSnippets[7] = "Sry, in qso nw, pse qrx, I will meep you"; +// +// textSnippets[8] = "Ur ant my dir nw?"; +// textSnippets[9] = "nil?"; +// textSnippets[10] = "No cw op here, could we use ssb?"; +// textSnippets[11] = "No chance in ssb, could we use cw?"; +// +// textSnippets[12] = "Nil till now, are you calling?"; +// textSnippets[13] = "Nil, I will look for an ap"; +// textSnippets[14] = "Tnx try, maybe later!"; +// textSnippets[15] = "Tnx fb qso, all ok, 73 es gl!"; + } + + /** + * Preferences for the preferences + * kst4contest@googlegroups.com + * praktimarc+kst4contest@gmail.com + * + */ + + String programVersion = "Chat is powered by ON4KST \n\nUsage is free. You are welcome to support: \n\n- my project (donations, bugreports, good ideas are welcome), \n- ON4KST Servers, \n- AirScout developers and \n- OV3T (best AS-data provider of the world). \n\n73 de DO5AMF, Marc (DM5M / DARC X08)"; + String logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = "udpReaderBackup.txt"; + String storeAndRestorePreferencesFileName = ApplicationFileUtils.getFilePath(ApplicationConstants.APPLICATION_NAME, PREFERENCES_FILE); + String chatState; // working variable only for use by primarystage (title bar) +// ObservableStringValue chatState; + + /** + * Station preferences + */ + + String loginCallSign = "do5amf"; + String loginPassword = ""; + String loginName = "Marc"; + String loginLocator = "jn49fk"; + ChatCategory loginChatCategory = new ChatCategory(2); + IntegerProperty actualQTF = new SimpleIntegerProperty(360); // will be updated by user at runtime! + + /** + * Log Synch preferences + */ + String logsynch_fileBasedWkdCallInterpreterFileNameReadOnly = "SimpleLogFile.txt"; + boolean logsynch_fileBasedWkdCallInterpreterEnabled = true; + + int logsynch_ucxUDPWkdCallListenerPort = 12060; + boolean logsynch_ucxUDPWkdCallListenerEnabled = true; + + /** + * TRX Synch prefs + */ + StringProperty MYQRG = new SimpleStringProperty(); // own qrg will be set by user entry or ucxlog if trx Synch is + // activated + boolean trxSynch_ucxLogUDPListenerEnabled = false; + + /** + * AirScout prefs + */ + boolean AirScout_asUDPListenerEnabled; + String AirScout_asServerNameString, AirScout_asClientNameString, AirScout_asBandString; + int AirScout_asCommunicationPort; + + /** + * Notification prefs + */ + + /** + * Shortcuts and Textsnippets prefs + */ +// String[] shortcuts = new String[37]; +// String[] textSnippets = new String[16]; + ObservableList lst_txtSnipList = FXCollections.observableArrayList(); + ObservableList lst_txtShortCutBtnList = FXCollections.observableArrayList(); + + /** + * Beacon prefs + */ + + boolean bcn_beaconsEnabled = true; + int bcn_beaconIntervalInMinutes = 20; + String bcn_beaconText = "Hi, pse call us"; + + /** + * Unworked station requester prefs + */ + + boolean unwkd_unworkedStnRequesterBeaconsEnabled; + int unwkd_unworkedStnRequesterBeaconsInterval; + String unwkd_unworkedStnRequesterBeaconsText; + String unwkd_beaconUnworkedstationsPrefix; + +// public String getMYQRG() { +// return MYQRG; +// } +// +// public void setMYQRG(String mYQRG) { +// +// MYQRG = mYQRG; +// } + + public String getLoginCallSign() { + return loginCallSign; + } + + public String getAirScout_asBandString() { + return AirScout_asBandString; + } + + public void setAirScout_asBandString(String airScout_asBandString) { + AirScout_asBandString = airScout_asBandString; + } + + public String getAirScout_asServerNameString() { + return AirScout_asServerNameString; + } + + public void setAirScout_asServerNameString(String airScout_asServerNameString) { + AirScout_asServerNameString = airScout_asServerNameString; + } + + public String getAirScout_asClientNameString() { + return AirScout_asClientNameString; + } + + public void setAirScout_asClientNameString(String airScout_asClientNameString) { + AirScout_asClientNameString = airScout_asClientNameString; + } + + public int getAirScout_asCommunicationPort() { + return AirScout_asCommunicationPort; + } + + public void setAirScout_asCommunicationPort(int airScout_asCommunicationPort) { + AirScout_asCommunicationPort = airScout_asCommunicationPort; + } + + public boolean isAirScout_asUDPListenerEnabled() { + return AirScout_asUDPListenerEnabled; + } + + public void setAirScout_asUDPListenerEnabled(boolean airScout_asUDPListenerEnabled) { + AirScout_asUDPListenerEnabled = airScout_asUDPListenerEnabled; + } + + public String getChatState() { + return chatState; + } + + public void setChatState(String chatState) { + this.chatState = chatState; + } + + public String getProgramVersion() { + return programVersion; + } + + public void setProgramVersion(String programVersion) { + this.programVersion = programVersion; + } + + public String getLogsynch_storeWorkedCallSignsFileNameUDPMessageBackup() { + return logsynch_storeWorkedCallSignsFileNameUDPMessageBackup; + } + + public void setLogsynch_storeWorkedCallSignsFileNameUDPMessageBackup( + String logsynch_storeWorkedCallSignsFileNameUDPMessageBackup) { + this.logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = logsynch_storeWorkedCallSignsFileNameUDPMessageBackup; + } + + /** + * actualQTF, int, QTF in degrees + * + * @param actualQTF, int, QTF in degrees + */ + + public StringProperty getMYQRG() { + return MYQRG; + } + + public IntegerProperty getActualQTF() { + return actualQTF; + } + + public void setActualQTF(IntegerProperty actualQTF) { + this.actualQTF = actualQTF; + } + + public void setMYQRG(StringProperty mYQRG) { + MYQRG = mYQRG; + } + + public void setLoginCallSign(String loginCallSign) { + this.loginCallSign = loginCallSign; + } + + public String getLoginPassword() { + return loginPassword; + } + + public void setLoginPassword(String loginPassword) { + this.loginPassword = loginPassword; + } + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } + + public String getLoginLocator() { + return loginLocator; + } + + public void setLoginLocator(String loginLocator) { + this.loginLocator = loginLocator; + } + + public ChatCategory getLoginChatCategory() { + return loginChatCategory; + } + + public void setLoginChatCategory(ChatCategory loginChatCategory) { + this.loginChatCategory = loginChatCategory; + } + + public String getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly() { + return logsynch_fileBasedWkdCallInterpreterFileNameReadOnly; + } + + public void setLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly( + String logsynch_fileBasedWkdCallInterpreterFileNameReadOnly) { + this.logsynch_fileBasedWkdCallInterpreterFileNameReadOnly = logsynch_fileBasedWkdCallInterpreterFileNameReadOnly; + } + + public boolean isLogsynch_fileBasedWkdCallInterpreterEnabled() { + return logsynch_fileBasedWkdCallInterpreterEnabled; + } + + public void setLogsynch_fileBasedWkdCallInterpreterEnabled(boolean logsynch_fileBasedWkdCallInterpreterEnabled) { + this.logsynch_fileBasedWkdCallInterpreterEnabled = logsynch_fileBasedWkdCallInterpreterEnabled; + } + + public int getLogsynch_ucxUDPWkdCallListenerPort() { + return logsynch_ucxUDPWkdCallListenerPort; + } + + public void setLogsynch_ucxUDPWkdCallListenerPort(int logsynch_ucxUDPWkdCallListenerPort) { + this.logsynch_ucxUDPWkdCallListenerPort = logsynch_ucxUDPWkdCallListenerPort; + } + + public boolean isLogsynch_ucxUDPWkdCallListenerEnabled() { + return logsynch_ucxUDPWkdCallListenerEnabled; + } + + public void setLogsynch_ucxUDPWkdCallListenerEnabled(boolean logsynch_ucxUDPWkdCallListenerEnabled) { + this.logsynch_ucxUDPWkdCallListenerEnabled = logsynch_ucxUDPWkdCallListenerEnabled; + } + + public boolean isTrxSynch_ucxLogUDPListenerEnabled() { + return trxSynch_ucxLogUDPListenerEnabled; + } + + public void setTrxSynch_ucxLogUDPListenerEnabled(boolean trxSynch_ucxLogUDPListenerEnabled) { + this.trxSynch_ucxLogUDPListenerEnabled = trxSynch_ucxLogUDPListenerEnabled; + } + +// public String[] getShortcuts() { +// return shortcuts; +// } +// +// public void setShortcuts(String[] shortcuts) { +// this.shortcuts = shortcuts; +// } + +// public String[] getTextSnippets() { +// return textSnippets; +// } +// +// public void setTextSnippets(String[] textSnippets) { +// this.textSnippets = textSnippets; +// } + + public boolean isBcn_beaconsEnabled() { + return bcn_beaconsEnabled; + } + + public ObservableList getLst_txtShortCutBtnList() { + return lst_txtShortCutBtnList; + } + + public void setLst_txtShortCutBtnList(ObservableList lst_txtShortCutBtnList) { + this.lst_txtShortCutBtnList = lst_txtShortCutBtnList; + } + + public ObservableList getLst_txtSnipList() { + return lst_txtSnipList; + } + + public void setLst_txtSnipList(ObservableList lst_txtSnipList) { + this.lst_txtSnipList = lst_txtSnipList; + } + + public void setBcn_beaconsEnabled(boolean bcn_beaconsEnabled) { + this.bcn_beaconsEnabled = bcn_beaconsEnabled; + } + + public int getBcn_beaconIntervalInMinutes() { + return bcn_beaconIntervalInMinutes; + } + + public void setBcn_beaconIntervalInMinutes(int bcn_beaconIntervalInMinutes) { + this.bcn_beaconIntervalInMinutes = bcn_beaconIntervalInMinutes; + } + + public String getBcn_beaconText() { + return bcn_beaconText; + } + + public void setBcn_beaconText(String bcn_beaconText) { + + this.bcn_beaconText = bcn_beaconText; + } + + + + public String getUnwkd_beaconUnworkedstationsPrefix() { + return unwkd_beaconUnworkedstationsPrefix; + } + + public void setUnwkd_beaconUnworkedstationsPrefix(String unwkd_beaconUnworkedstationsPrefix) { + this.unwkd_beaconUnworkedstationsPrefix = unwkd_beaconUnworkedstationsPrefix; + } + + public boolean isUnwkd_unworkedStnRequesterBeaconsEnabled() { + return unwkd_unworkedStnRequesterBeaconsEnabled; + } + + public void setUnwkd_unworkedStnRequesterBeaconsEnabled(boolean unwkd_unworkedStnRequesterBeaconsEnabled) { + this.unwkd_unworkedStnRequesterBeaconsEnabled = unwkd_unworkedStnRequesterBeaconsEnabled; + } + + public int getUnwkd_unworkedStnRequesterBeaconsInterval() { + return unwkd_unworkedStnRequesterBeaconsInterval; + } + + public void setUnwkd_unworkedStnRequesterBeaconsInterval(int unwkd_unworkedStnRequesterBeaconsInterval) { + this.unwkd_unworkedStnRequesterBeaconsInterval = unwkd_unworkedStnRequesterBeaconsInterval; + } + + public String getUnwkd_unworkedStnRequesterBeaconsText() { + return unwkd_unworkedStnRequesterBeaconsText; + } + + public void setUnwkd_unworkedStnRequesterBeaconsText(String unwkd_unworkedStnRequesterBeaconsText) { + this.unwkd_unworkedStnRequesterBeaconsText = unwkd_unworkedStnRequesterBeaconsText; + } + + public String getLogSynch_storeWorkedCallSignsFileNameUDPMessageBackup() { + return logsynch_storeWorkedCallSignsFileNameUDPMessageBackup; + } + + public void setLogSynch_storeWorkedCallSignsFileNameUDPMessageBackup( + String logSynch_storeWorkedCallSignsFileNameUDPMessageBackup) { + this.logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = logSynch_storeWorkedCallSignsFileNameUDPMessageBackup; + } + + public String getStoreAndRestorePreferencesFileName() { + return storeAndRestorePreferencesFileName; + } + + public void setStoreAndRestorePreferencesFileName(String storeAndRestorePreferencesFileName) { + this.storeAndRestorePreferencesFileName = storeAndRestorePreferencesFileName; + } + + /** + * + * @return true if the file writing was successful, else false + */ + public boolean writePreferencesToXmlFile() { + + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + try { + + // root elements + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.newDocument(); + Element rootElement = doc.createElement("praktiKST"); + doc.appendChild(rootElement); + + + Element station = doc.createElement("station"); + rootElement.appendChild(station); + + Element LoginCallSign = doc.createElement("LoginCallSign"); + LoginCallSign.setTextContent(this.getLoginCallSign()); + station.appendChild(LoginCallSign); + + + Element LoginPassword = doc.createElement("LoginPassword"); + LoginPassword.setTextContent(this.getLoginPassword()); + station.appendChild(LoginPassword); + + Element LoginDisplayedName = doc.createElement("LoginDisplayedName"); + LoginDisplayedName.setTextContent(this.getLoginName()); + station.appendChild(LoginDisplayedName); + + Element LoginLocator = doc.createElement("LoginLocator"); + LoginLocator.setTextContent(this.getLoginLocator()); + station.appendChild(LoginLocator); + + Element ChatCategory = doc.createElement("ChatCategory"); + ChatCategory.setTextContent(this.getLoginChatCategory().getCategoryNumber()+""); + station.appendChild(ChatCategory); + +// Element salary = doc.createElement("salary"); +// salary.setAttribute("currency", "USD"); +// salary.setTextContent("5000"); +// staff.appendChild(salary); + + // add xml comment + Comment comment = doc.createComment( + "for special characters like < &, need CDATA"); +// staff.appendChild(comment); + +// Element bio = doc.createElement("bio"); + // add xml CDATA + +// staff.appendChild(bio); + + /** + * LOGSYNCH + */ + + Element logsynch = doc.createElement("logsynch"); + rootElement.appendChild(logsynch); + + Element logsynch_fileBasedWkdCallInterpreterFileNameReadOnly = doc.createElement("logsynch_fileBasedWkdCallInterpreterFileNameReadOnly"); + logsynch_fileBasedWkdCallInterpreterFileNameReadOnly.setTextContent(this.getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly()); + logsynch.appendChild(logsynch_fileBasedWkdCallInterpreterFileNameReadOnly); + + Element logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = doc.createElement("logsynch_storeWorkedCallSignsFileNameUDPMessageBackup"); + logsynch_storeWorkedCallSignsFileNameUDPMessageBackup.setTextContent(this.getLogsynch_storeWorkedCallSignsFileNameUDPMessageBackup()); + logsynch.appendChild(logsynch_storeWorkedCallSignsFileNameUDPMessageBackup); + + Element logsynch_fileBasedWkdCallInterpreterEnabled = doc.createElement("logsynch_fileBasedWkdCallInterpreterEnabled"); + logsynch_fileBasedWkdCallInterpreterEnabled.setTextContent(this.isLogsynch_fileBasedWkdCallInterpreterEnabled()+""); + logsynch.appendChild(logsynch_fileBasedWkdCallInterpreterEnabled); + + Element logsynch_ucxUDPWkdCallListenerPort = doc.createElement("logsynch_ucxUDPWkdCallListenerPort"); + logsynch_ucxUDPWkdCallListenerPort.setTextContent(this.getLogsynch_ucxUDPWkdCallListenerPort()+""); + logsynch.appendChild(logsynch_ucxUDPWkdCallListenerPort); + + Element logsynch_ucxUDPWkdCallListenerEnabled = doc.createElement("logsynch_ucxUDPWkdCallListenerEnabled"); + logsynch_ucxUDPWkdCallListenerEnabled.setTextContent(this.isTrxSynch_ucxLogUDPListenerEnabled()+""); + logsynch.appendChild(logsynch_ucxUDPWkdCallListenerEnabled); + + + /** + * trxSynchUCX + */ + + Element trxSynchUCX = doc.createElement("trxSynchUCX"); + rootElement.appendChild(trxSynchUCX); + + Element trxSynch_ucxLogUDPListenerEnabled = doc.createElement("trxSynch_ucxLogUDPListenerEnabled"); + trxSynch_ucxLogUDPListenerEnabled.setTextContent(this.isTrxSynch_ucxLogUDPListenerEnabled()+""); + trxSynchUCX.appendChild(trxSynch_ucxLogUDPListenerEnabled); + + Element trxSynch_defaultMYQRGValue = doc.createElement("trxSynch_defaultMYQRGValue"); + trxSynch_defaultMYQRGValue.setTextContent(this.getMYQRG().getValue()); + trxSynchUCX.appendChild(trxSynch_defaultMYQRGValue); + + + + + /** + * AirScout + */ + + Element AirScoutQuerier = doc.createElement("AirScoutQuerier"); + rootElement.appendChild(AirScoutQuerier); + + + Element asQry_airScoutCommunicationEnabled = doc.createElement("asQry_airScoutCommunicationEnabled"); + asQry_airScoutCommunicationEnabled.setTextContent(this.isAirScout_asUDPListenerEnabled()+""); + AirScoutQuerier.appendChild(asQry_airScoutCommunicationEnabled); + + Element asQry_airScoutServerName = doc.createElement("asQry_airScoutServerName"); + asQry_airScoutServerName.setTextContent(this.getAirScout_asServerNameString()); + AirScoutQuerier.appendChild(asQry_airScoutServerName); + + Element asQry_airScoutClientName = doc.createElement("asQry_airScoutClientName"); + asQry_airScoutClientName.setTextContent(this.getAirScout_asClientNameString()); + AirScoutQuerier.appendChild(asQry_airScoutClientName); + + Element asQry_airScoutUDPPort = doc.createElement("asQry_airScoutUDPPort"); + asQry_airScoutUDPPort.setTextContent(this.getAirScout_asCommunicationPort()+""); + AirScoutQuerier.appendChild(asQry_airScoutUDPPort); + + Element asQry_airScoutBandValue = doc.createElement("asQry_airScoutBandValue"); + asQry_airScoutBandValue.setTextContent(this.getAirScout_asBandString()); + AirScoutQuerier.appendChild(asQry_airScoutBandValue); + + /** + * Shortcuts + */ + + Element shortCuts = doc.createElement("shortCuts"); + rootElement.appendChild(shortCuts); + + for (Iterator iterator = lst_txtShortCutBtnList.iterator(); iterator.hasNext();) { + String string = (String) iterator.next(); + Element temp = doc.createElement("t"); + temp.setTextContent(string); + shortCuts.appendChild(temp); + } + + /** + * Textsnippets (right click menu) + */ + + Element textSnippets = doc.createElement("textSnippets"); + rootElement.appendChild(textSnippets); + + for (Iterator iterator = lst_txtSnipList.iterator(); iterator.hasNext();) { + String string = (String) iterator.next(); + Element temp = doc.createElement("t"); + temp.setTextContent(string); + textSnippets.appendChild(temp); + } + + + /** + * BeaconCQ + */ + + Element beaconCQ = doc.createElement("beaconCQ"); + rootElement.appendChild(beaconCQ); + + + Element beaconCQText = doc.createElement("beaconCQText"); + beaconCQText.setTextContent(this.getBcn_beaconText()); + beaconCQ.appendChild(beaconCQText); + + Element beaconCQIntervalMinutes = doc.createElement("beaconCQIntervalMinutes"); + beaconCQIntervalMinutes.setTextContent(this.getBcn_beaconIntervalInMinutes()+""); + beaconCQ.appendChild(beaconCQIntervalMinutes); + + Element beaconCQEnabled = doc.createElement("beaconCQEnabled"); + beaconCQEnabled.setTextContent(this.isBcn_beaconsEnabled()+""); + beaconCQ.appendChild(beaconCQEnabled); + + + + /** + * Beacon Unworked Stations + */ + + Element beaconUnworkedstations = doc.createElement("beaconUnworkedstations"); + rootElement.appendChild(beaconUnworkedstations); + + + Element beaconUnworkedstationsText = doc.createElement("beaconUnworkedstationsText"); + beaconUnworkedstationsText.setTextContent(this.getUnwkd_unworkedStnRequesterBeaconsText()); + beaconUnworkedstations.appendChild(beaconUnworkedstationsText); + + Element beaconUnworkedstationsIntervalMinutes = doc.createElement("beaconUnworkedstationsIntervalMinutes"); + beaconUnworkedstationsIntervalMinutes.setTextContent(this.getUnwkd_unworkedStnRequesterBeaconsInterval()+""); + beaconUnworkedstations.appendChild(beaconUnworkedstationsIntervalMinutes); + + Element beaconUnworkedstationsEnabled = doc.createElement("beaconUnworkedstationsEnabled"); + beaconUnworkedstationsEnabled.setTextContent(this.isUnwkd_unworkedStnRequesterBeaconsEnabled()+""); + beaconUnworkedstations.appendChild(beaconUnworkedstationsEnabled); + + Element beaconUnworkedstationsPrefix = doc.createElement("beaconUnworkedstationsPrefix"); + beaconUnworkedstationsPrefix.setTextContent(this.getUnwkd_beaconUnworkedstationsPrefix()); + beaconUnworkedstations.appendChild(beaconUnworkedstationsPrefix); + + + + writeXml(doc, System.out); + + // write dom document to a file + try (FileOutputStream output = + new FileOutputStream(storeAndRestorePreferencesFileName)) { + writeXml(doc, output); + } catch (IOException e) { + e.printStackTrace(); + } catch (TransformerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + } catch (ParserConfigurationException | TransformerException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + return true; + + // root elements + + //...create XML elements, and others... + + // write dom document to a file + + } + + // write doc to output stream + private static void writeXml(Document doc, OutputStream output) throws TransformerException { + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(output); + + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + + transformer.transform(source, result); + + } + + /** + * + * @return true if the file reading was successful, else false + */ + public boolean readPreferencesFromXmlFile() { + + System.out.println("[ChatPreferences, Info]: restoring prefs from file " + storeAndRestorePreferencesFileName); + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + try { + + File xmlConfigFile = new File(storeAndRestorePreferencesFileName); + + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.parse(xmlConfigFile); + + /** + * case station settings + * + */ + NodeList list = doc.getElementsByTagName("station"); + 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("LoginCallSign").item(0).getTextContent(); + loginCallSign = call; + +// call = call.toLowerCase(); + String password = element.getElementsByTagName("LoginPassword").item(0).getTextContent(); + loginPassword = password; + + String loginDisplayedName = element.getElementsByTagName("LoginDisplayedName").item(0) + .getTextContent(); + loginName = loginDisplayedName; + + String qra = element.getElementsByTagName("LoginLocator").item(0).getTextContent(); + loginLocator = qra; + + String category = element.getElementsByTagName("ChatCategory").item(0).getTextContent(); + + if (isNumeric(category)) { + ChatCategory chatCategory = new ChatCategory(Integer.parseInt(category)); + loginChatCategory = chatCategory; + } else { + + loginChatCategory = new ChatCategory(2); // TODO: Set this default at another place + } + + System.out.println("[ChatPreferences, info]: Current Element: " + node.getNodeName() + + " --> call: " + call + " / " + password + " / " + loginDisplayedName + " / " + qra + + " / " + category); + + } + } + } + + /** + * Case log synchronizatrion + */ + + list = doc.getElementsByTagName("logsynch"); + 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 logsynchReadFile = element + .getElementsByTagName("logsynch_fileBasedWkdCallInterpreterFileNameReadOnly").item(0) + .getTextContent(); + + logsynch_fileBasedWkdCallInterpreterFileNameReadOnly = logsynchReadFile; + + String UDPMessageBackupFileName = element + .getElementsByTagName("logsynch_storeWorkedCallSignsFileNameUDPMessageBackup").item(0) + .getTextContent(); + + logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = UDPMessageBackupFileName; + +// call = call.toLowerCase(); + String fileBasedLogSynchEnabled = element + .getElementsByTagName("logsynch_fileBasedWkdCallInterpreterEnabled").item(0) + .getTextContent(); + + if (fileBasedLogSynchEnabled.equals("true")) { + + logsynch_fileBasedWkdCallInterpreterEnabled = true; + } else { + logsynch_fileBasedWkdCallInterpreterEnabled = false; + } + + String ucxUDPLogSynchListenerPort = element + .getElementsByTagName("logsynch_ucxUDPWkdCallListenerPort").item(0).getTextContent(); + + if (isNumeric(ucxUDPLogSynchListenerPort)) { + logsynch_ucxUDPWkdCallListenerPort = Integer.parseInt(ucxUDPLogSynchListenerPort); + } else { + logsynch_ucxUDPWkdCallListenerPort = 12060; // TODO: Set default at another place or with + // STATIC VAR + } + + String ucxUDPLogSynchListenerEnabled = element + .getElementsByTagName("logsynch_ucxUDPWkdCallListenerEnabled").item(0).getTextContent(); + + if (ucxUDPLogSynchListenerEnabled.equals("true")) { + logsynch_ucxUDPWkdCallListenerEnabled = true; + } else { + logsynch_ucxUDPWkdCallListenerEnabled = false; + } + + System.out.println( + "[ChatPreferences, info]: Set the Universal file based worked-Call Interpreter to : " + + logsynch_fileBasedWkdCallInterpreterEnabled); + + System.out.println("[ChatPreferences, info]: Set the UCX UDP Worked Call Listener to : " + + logsynch_ucxUDPWkdCallListenerEnabled); + + } + } + } + + /** + * Case trx synchronizatrion + */ + + list = doc.getElementsByTagName("trxSynchUCX"); + 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 trxSynchUCX = element.getElementsByTagName("trxSynch_ucxLogUDPListenerEnabled").item(0) + .getTextContent(); + + if (trxSynchUCX.equals("true")) { + trxSynch_ucxLogUDPListenerEnabled = true; + } else { + trxSynch_ucxLogUDPListenerEnabled = false; + } + + String trxSynch_defaultMYQRGValue = element.getElementsByTagName("trxSynch_defaultMYQRGValue") + .item(0).getTextContent(); + + this.getMYQRG().setValue(trxSynch_defaultMYQRGValue); + +// this.getMYQRG().addListener((observable, oldValue, newValue) -> { +// System.out.println("[Chatprefs.java, Info]: MYQRG changed from " + oldValue + " to " + newValue); +//// this.getMYQRG(). +//// txt_ownqrg.setText(newValue); +// }); + +// + System.out.println( + "[ChatPreferences, info]: Set the trx qrg synch to " + trxSynch_ucxLogUDPListenerEnabled + + " and default value to " + this.getMYQRG().getValue()); + + } + } + } + + /** + * Case AirScout querier + */ + + list = doc.getElementsByTagName("AirScoutQuerier"); + 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 asQuerierUDPEnabled = element.getElementsByTagName("asQry_airScoutCommunicationEnabled") + .item(0).getTextContent(); + + if (asQuerierUDPEnabled.equals("true")) { + AirScout_asUDPListenerEnabled = true; + } else { + AirScout_asUDPListenerEnabled = false; + } + + this.setAirScout_asServerNameString( + element.getElementsByTagName("asQry_airScoutServerName").item(0).getTextContent()); + this.setAirScout_asClientNameString( + element.getElementsByTagName("asQry_airScoutClientName").item(0).getTextContent()); + this.setAirScout_asCommunicationPort(Integer.parseInt( + element.getElementsByTagName("asQry_airScoutUDPPort").item(0).getTextContent())); + this.setAirScout_asBandString( + element.getElementsByTagName("asQry_airScoutBandValue").item(0).getTextContent()); +// this.getMYQRG().addListener((observable, oldValue, newValue) -> { +// System.out.println("[Chatprefs.java, Info]: MYQRG changed from " + oldValue + " to " + newValue); +//// this.getMYQRG(). +//// txt_ownqrg.setText(newValue); +// }); + +// + System.out.println("[ChatPreferences, info]: Set the Airscout Querier to " + asQuerierUDPEnabled + + " for qrg " + AirScout_asBandString); + + } + } + } + + /** + * Case shortCuts + */ + + list = doc.getElementsByTagName("shortCuts"); + String[] shortCutsExtractedOutOfXML = new String[0]; + + if (list.getLength() != 0) { + + ArrayList textShorts = new ArrayList(); + + for (int temp = 0; temp < list.getLength(); temp++) { + + Node node = list.item(temp); + + Element element = (Element) node; + + for (int i = 0; i < element.getChildNodes().getLength(); i++) { + if (element.getChildNodes().item(i).getNodeType() == Node.ELEMENT_NODE) { + textShorts.add(element.getChildNodes().item(i).getTextContent()); + shortCutsExtractedOutOfXML = textShorts.toArray(String[]::new); // String[]::new = API + // Collection.toArray(IntFunction + // generator) +// System.out.println(element.getChildNodes().item(i).getNodeType() + ": " + element.getChildNodes().item(i).getNodeName() + " - " + element.getChildNodes().item(i).getTextContent()); + } + } + + } + + // if praktiKST found Shortcuts in the configfile, set it to the preferences +// shortcuts = shortCutsExtractedOutOfXML; + // else use defaults (as the initialization vars had been) + for (int i = 0; i < shortCutsExtractedOutOfXML.length; i++) { + lst_txtShortCutBtnList.add(shortCutsExtractedOutOfXML[i]); + System.out.println("[Chatpreferences, Info]: Setting Short " + i + " \"" + + shortCutsExtractedOutOfXML[i] + "\""); + } + } + + /** + * Case textSnippets + */ + + list = doc.getElementsByTagName("textSnippets"); + String[] textSnippetsExtractedOutOfXML = new String[0]; + + if (list.getLength() != 0) { + + ArrayList textShorts = new ArrayList(); + + for (int temp = 0; temp < list.getLength(); temp++) { + + Node node = list.item(temp); + + Element element = (Element) node; + + for (int i = 0; i < element.getChildNodes().getLength(); i++) { + if (element.getChildNodes().item(i).getNodeType() == Node.ELEMENT_NODE) { + textShorts.add(element.getChildNodes().item(i).getTextContent()); + textSnippetsExtractedOutOfXML = textShorts.toArray(String[]::new); // String[]::new = API + // Collection.toArray(IntFunction + // generator) +// System.out.println(element.getChildNodes().item(i).getNodeType() + ": " + element.getChildNodes().item(i).getNodeName() + " - " + element.getChildNodes().item(i).getTextContent()); + } + } + + } + + // if praktiKST found Shortcuts in the configfile, set it to the preferences +// textSnippets = textSnippetsExtractedOutOfXML; + // else use defaults (as the initialization vars had been) + for (int i = 0; i < textSnippetsExtractedOutOfXML.length; i++) { + lst_txtSnipList.add(textSnippetsExtractedOutOfXML[i]); + System.out.println("[Chatpreferences, Info]: Setting Snip " + i + " \"" + + textSnippetsExtractedOutOfXML[i] + "\""); + } + } + + /** + * Case beaconCQ + */ + + list = doc.getElementsByTagName("beaconCQ"); + 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 beaconCQEnabled = element.getElementsByTagName("beaconCQEnabled").item(0) + .getTextContent(); + + if (beaconCQEnabled.equals("true")) { + + bcn_beaconsEnabled = true; + } else { + bcn_beaconsEnabled = false; + } + + String beaconCQIntervalMinutes = element.getElementsByTagName("beaconCQIntervalMinutes").item(0) + .getTextContent(); + + if (isNumeric(beaconCQIntervalMinutes)) { + bcn_beaconIntervalInMinutes = Integer.parseInt(beaconCQIntervalMinutes); + } else { + bcn_beaconIntervalInMinutes = 20; // Default value, TODO: Set this in default list + } + + String beaconCQText = element.getElementsByTagName("beaconCQText").item(0).getTextContent(); + this.setBcn_beaconText(beaconCQText); + +// + System.out.println("[ChatPreferences, info]: set the beacon text to: " + beaconCQText); + + } + } + } + + /** + * Case beaconUnworkedstations + * + */ + + list = doc.getElementsByTagName("beaconUnworkedstations"); + 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 beaconUnworkedstationsText = element.getElementsByTagName("beaconUnworkedstationsText") + .item(0).getTextContent(); + unwkd_unworkedStnRequesterBeaconsText = beaconUnworkedstationsText; + + String beaconUnworkedstationsIntervalMinutes = element + .getElementsByTagName("beaconUnworkedstationsIntervalMinutes").item(0).getTextContent(); + + if (isNumeric(beaconUnworkedstationsIntervalMinutes)) { + unwkd_unworkedStnRequesterBeaconsInterval = Integer + .parseInt(beaconUnworkedstationsIntervalMinutes); + } else { + unwkd_unworkedStnRequesterBeaconsInterval = 20; + } + + String beaconUnworkedstationsEnabled = element + .getElementsByTagName("beaconUnworkedstationsEnabled").item(0).getTextContent(); + + if (beaconUnworkedstationsEnabled.equals("true")) { + unwkd_unworkedStnRequesterBeaconsEnabled = true; + } else { + unwkd_unworkedStnRequesterBeaconsEnabled = false; + } + + String beaconUnworkedstationsPrefix = element + .getElementsByTagName("beaconUnworkedstationsPrefix").item(0).getTextContent(); + + unwkd_beaconUnworkedstationsPrefix = beaconUnworkedstationsPrefix; + + } + } + System.out.println("[ChatPreferences, info]: set the unworked stn beacon text to: " + + unwkd_unworkedStnRequesterBeaconsText); + } + + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + System.out.println(e.getCause()); + System.out.println(e.getMessage()); + } + + return true; + + } + + + /** + * + * If the file-reading goes wrong, set the defaults + */ + public void setPreferencesDefaults() { + System.out.println("[ChatPreferences, Info]: restoring prefs from defaults"); + + } + + /** + * 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 + */ + private static boolean isNumeric(String str) { + return str != null && str.matches("[0-9.]+"); + } + +// public ObservableList getTxtSnippetsAsObservableList(){ +// ObservableList lst_txtSnipList = FXCollections.observableArrayList(); +// +// for (int i = 0; i < textSnippets.length; i++) { +// lst_txtSnipList.add(textSnippets[i]); +// System.out.println(textSnippets[i]); +// } +// +// return lst_txtSnipList; +// +// } + +} diff --git a/src/main/java/kst4contest/model/ClusterMessage.java b/src/main/java/kst4contest/model/ClusterMessage.java new file mode 100644 index 0000000..887abd1 --- /dev/null +++ b/src/main/java/kst4contest/model/ClusterMessage.java @@ -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; + } + + + +} diff --git a/src/main/java/kst4contest/utils/ApplicationFileUtils.java b/src/main/java/kst4contest/utils/ApplicationFileUtils.java new file mode 100644 index 0000000..3f457cd --- /dev/null +++ b/src/main/java/kst4contest/utils/ApplicationFileUtils.java @@ -0,0 +1,69 @@ +package kst4contest.utils; + +import kst4contest.controller.DBController; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; + +/** + * This class has utility methods to handle application files inside the home directory. + */ +public class ApplicationFileUtils { + + /** + * Gets the path of a file inside the home directory of the user. + * @param applicationName Name off the application which is used for the hidden directory + * @param fileName Name of the file. + * @return The full path inside the user home directory. + */ + public static String getFilePath(final String applicationName, final String fileName) { + return Path.of(System.getProperty("user.home"), + "." + applicationName, + fileName).toString(); + } + + /** + * Copies a resource to the application folder if required. + * @param applicationName Name of the application. + * @param resourcePath Path of the resource. + * @param fileName Name of the target file. + */ + public static void copyResourceIfRequired(final String applicationName, final String resourcePath, final String fileName) { + File file = new File(getFilePath(applicationName, fileName)); + + if (file.exists()) { + return; + } + + File parentDir = file.getParentFile(); + if (!parentDir.exists()) { + parentDir.mkdirs(); + } + + copyResourceToFile(resourcePath, file.getPath()); + } + + /** + * Copies a given resource at a resourcePath to the file path. + * @param resourcePath + * @param filePath + */ + public static void copyResourceToFile(String resourcePath, String filePath) { + try (InputStream resourceStream = ApplicationFileUtils.class.getResourceAsStream(resourcePath); + FileOutputStream fileOutputStream = new FileOutputStream(filePath)) { + + if (resourceStream == null) { + throw new IllegalArgumentException("Resource not found: " + resourcePath); + } + + resourceStream.transferTo(fileOutputStream); + } catch (IOException ex) { + System.err.println("Exception when copying Application file: " + ex.getMessage()); + ex.printStackTrace(System.err); + } + } + +} diff --git a/src/main/java/kst4contest/view/GuiUtils.java b/src/main/java/kst4contest/view/GuiUtils.java new file mode 100644 index 0000000..9531991 --- /dev/null +++ b/src/main/java/kst4contest/view/GuiUtils.java @@ -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.]+"); + } + +} diff --git a/src/main/java/kst4contest/view/Kst4ContestApplication.java b/src/main/java/kst4contest/view/Kst4ContestApplication.java new file mode 100644 index 0000000..0abcef9 --- /dev/null +++ b/src/main/java/kst4contest/view/Kst4ContestApplication.java @@ -0,0 +1,3220 @@ +package kst4contest.view; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.Iterator; +import java.util.Optional; +import java.util.Timer; +import java.util.TimerTask; + +import kst4contest.controller.ChatController; +import kst4contest.controller.Utils4KST; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.geometry.Pos; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.Menu; +import javafx.scene.control.MenuBar; +import javafx.scene.control.MenuItem; +import javafx.scene.control.PasswordField; +import javafx.scene.control.SelectionMode; +import javafx.scene.control.Separator; +import javafx.scene.control.SplitPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableColumn.CellDataFeatures; +import javafx.scene.control.TableColumn.CellEditEvent; +import javafx.scene.control.TableView; +import javafx.scene.control.TableView.TableViewSelectionModel; +import javafx.scene.control.TextField; +import javafx.scene.control.Tooltip; +import javafx.scene.control.cell.TextFieldTableCell; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; +import javafx.util.Callback; +import kst4contest.model.ChatCategory; +import kst4contest.model.ChatMember; +import kst4contest.model.ChatMessage; +import kst4contest.model.ClusterMessage; + +public class Kst4ContestApplication extends Application { + + String chatState; + ChatController chatcontroller; + Button MYQRGButton; // TODO: clean code? Got the myqrg button out of the factory method to modify + // the text later + Button MYCALLSetQRGButton; + + Timer timer_buildWindowTitle; + Timer timer_chatMemberTableSortTimer; // need that because javafx bug, it´s the only way to actualize the table... + Timer timer_updatePrivatemessageTable; // same here + + private TableView initChatMemberTable() { + + TableView tbl_chatMemberTable = new TableView(); + tbl_chatMemberTable.setTooltip(new Tooltip( + "Stations available \n\n Use right click to a station to select predefined texts \n\n Texts can be changed in the config-file")); + + TableColumn callSignCol = new TableColumn("Callsign"); + callSignCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callsgn = new SimpleStringProperty(); + + callsgn.setValue(cellDataFeatures.getValue().getCallSign()); + + return callsgn; + } + }); + + TableColumn nameCol = new TableColumn("Name"); + nameCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty name = new SimpleStringProperty(); + + name.setValue(cellDataFeatures.getValue().getName()); + + return name; + } + }); + + TableColumn qraCol = new TableColumn("QRA"); + qraCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty qra = new SimpleStringProperty(); + + qra.setValue(cellDataFeatures.getValue().getQra()); + + return qra; + } + }); + + TableColumn qrgCol = new TableColumn("QRG"); + qrgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { +// StringProperty qrg = new SimpleStringProperty(); + +// qrg.setValue(cellDataFeatures.getValue().getFrequency()); +// qrg = (cellDataFeatures.getValue().getFrequency()); + +// if (!qrg.getValue().equals("")) { +// +// } + + return cellDataFeatures.getValue().getFrequency(); + } + + }); + + TableColumn airScoutCol = new TableColumn("AP [minutes / pot%]"); + airScoutCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty airPlaneInfo = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes() == null) { + airPlaneInfo.setValue(" "); + } + + else if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().size() <= 0) { + airPlaneInfo.setValue(" "); + } else { + String apInfoText = "" + + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(0) + .getArrivingDurationMinutes() + + " (" + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(0) + .getPotential() + + "%)"; +// +// + if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().size() > 1) { + apInfoText += " / " + + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(1) + .getArrivingDurationMinutes() + + " (" + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes() + .get(1).getPotential() + + "%)"; + } + + airPlaneInfo.setValue(apInfoText); + } + + return airPlaneInfo; + } + }); + /** + * HIGH EXPERIMENTAL:::::::: + */ + airScoutCol.setCellFactory(new Callback, TableCell>() { + public TableCell call(TableColumn param) { + return new TableCell() { + + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (!isEmpty()) { + this.setTextFill(Color.BLACK); + // Get fancy and change color based on data + if (item.contains("100%")) { + this.setTextFill(Color.BLUEVIOLET); + } else if (item.contains("75%") && !item.contains("100%")) { + this.setTextFill(Color.RED); + } else if (item.contains("50%") && ((!item.contains("100%")) || (!item.contains("75%")))) { + this.setTextFill(Color.ORANGE); + } + + setText(item); + } + } + }; + } + }); + /** + * END HIGH EXPERIMENTAL:::::::: + */ + + TableColumn workedCol = new TableColumn("worked"); + workedCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + TableColumn wkdAny_subcol = new TableColumn("wkd"); + wkdAny_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + wkdAny_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28)); + + TableColumn vhfCol_subcol = new TableColumn("144"); + vhfCol_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked144()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + vhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28)); + + TableColumn uhfCol_subcol = new TableColumn("432"); + uhfCol_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked432()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + uhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28)); + + TableColumn shf23_subcol = new TableColumn("23"); + shf23_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked1240()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf23_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(30)); + + TableColumn shf13_subcol = new TableColumn("13"); + shf13_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked2300()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf13_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(30)); + + TableColumn shf9_subcol = new TableColumn("9"); + shf9_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked3400()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf9_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32)); + + TableColumn shf6_subcol = new TableColumn("6"); + shf6_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked5600()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf6_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32)); + + TableColumn shf3_subcol = new TableColumn("3"); + shf3_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked10G()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + shf3_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32)); + +// TableColumn uhfCol_subcol = new TableColumn("432"); //TODO: Worked band analysis +// TableColumn shf23_subcol = new TableColumn("23"); +// TableColumn shf13_subcol = new TableColumn("13"); +// TableColumn shf9_subcol = new TableColumn("9"); +// TableColumn shf6_subcol = new TableColumn("6"); +// TableColumn shf3_subcol = new TableColumn("3"); + workedCol.getColumns().addAll(wkdAny_subcol, vhfCol_subcol, uhfCol_subcol, shf23_subcol, shf13_subcol, + shf9_subcol, shf6_subcol, shf3_subcol); // TODO: automatize enabling to users bandChoice + + tbl_chatMemberTable.getColumns().addAll(callSignCol, nameCol, qraCol, qrgCol, airScoutCol, workedCol); + + tbl_chatMemberTable.setItems(chatcontroller.getLst_chatMemberList()); + +// chatcontroller.getLst_chatMemberList().addListener(new ListChangeListener() { +//// ObservableStringValue chatState = new SimpleStringProperty(); +// +// @Override +// public void onChanged(javafx.collections.ListChangeListener.Change pChange) { +//// while (pChange.next()) { +//// System.out.println("List changed"); +// +// //TODO: Das kann man ggf anders machen +// +// String chatState = chatcontroller.getChatPreferences().getProgramVersion() + " / " +// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / " +// + chatcontroller.getLst_chatMemberList().size() + " users online."; +// chatcontroller.getChatPreferences().setChatState(chatState); +// +//// chatcontroller.getChatPreferences().setChatState(chatcontroller.getChatPreferences().getProgramVersion() + " / " +//// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / " +//// + chatcontroller.getLst_chatMemberList().size() + " users online."); +//// primaryStage.setTitle("asdf"); +//// primaryStage.setTitle(chatcontroller.getChatPreferences().getProgramVersion() + " / " +//// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / " +//// + chatcontroller.getLst_chatMemberList().size() + " users online."); +//// } +// } +// }); + + tbl_chatMemberTable.getSortOrder().add(callSignCol); + + /** + * timer_chatMemberTableSortTimer --> + * This part fixes a javafx bug. The update of the Chatmember fields is (for any + * reason) not visible in the ui. Its neccessarry to sort the table in intervals + * to keep the table up to date. Otherwise + */ + + timer_chatMemberTableSortTimer = new Timer(); + + timer_chatMemberTableSortTimer.scheduleAtFixedRate(new TimerTask() { + + public void run() { + Thread.currentThread().setName("chatMemberTableSortTimer"); + + Platform.runLater(() -> { + + try { + +// tbl_chatMemberTable.sort(); + + } catch (Exception e) { + System.out.println("[Main.java, Warning:] Table sorting (actualizing) failed this time."); + } + + tbl_chatMemberTable.refresh(); + + }); + } + }, new Date(), 3000); + + tbl_chatMemberTable.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY); + tbl_chatMemberTable.autosize(); + + return tbl_chatMemberTable; + } + + /** + * Initializes the right click contextmenu for the chatmember-table, sets the + * clickhandler for the contextmenu out of a string array (each menuitam will be + * created out of exact one array-entry). These are initialized by the + * chatpreferences object out of the config-xml + * + * @param menuTexts + * @return + */ +// private ContextMenu initChatMemberTableContextMenu(String[] menuTexts) { old mechanic +// +// ContextMenu chatMemberContextMenu = new ContextMenu(); +// +// for (int i = 0; i < menuTexts.length; i++) { +// final MenuItem menuItem = new MenuItem(menuTexts[i]); +// menuItem.setOnAction(new EventHandler() { +// public void handle(ActionEvent event) { +// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + menuItem.getText()); +// } +// }); +// +// chatMemberContextMenu.getItems().add(menuItem); +// } +// +//// MenuItem macro1 = new MenuItem("Pse Sked?"); +//// macro1.setOnAction(new EventHandler() { +//// public void handle(ActionEvent event) { +//// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + macro1.getText()); +//// } +//// }); +//// MenuItem macro10 = new MenuItem("Pse qrg 2m?"); +//// MenuItem macro20 = new MenuItem("Pse Call at "); +//// MenuItem macro30 = new MenuItem("In qso nw, pse qrx, I will meep you"); +//// MenuItem macro40 = new MenuItem("Pse qrg 70cm?"); +//// MenuItem macro50 = new MenuItem("pse qrg 23cm?"); +//// MenuItem macro60 = new MenuItem("____________________________________"); +//// MenuItem macro70 = new MenuItem("Watch QSO history"); +//// +//// chatMemberContextMenu.getItems().add(macro1); +//// chatMemberContextMenu.getItems().add(macro10); +//// chatMemberContextMenu.getItems().add(macro20); +//// chatMemberContextMenu.getItems().add(macro30); +//// chatMemberContextMenu.getItems().add(macro40); +//// chatMemberContextMenu.getItems().add(macro50); +//// chatMemberContextMenu.getItems().add(macro60); +//// chatMemberContextMenu.getItems().add(macro70); +// +// return chatMemberContextMenu; +// +// } + + /** + * Initializes the right click contextmenu for the chatmember-table, sets the + * clickhandler for the contextmenu out of a string array (each menuitam will be + * created out of exact one array-entry). These are initialized by the + * chatpreferences object out of the config-xml + * + * @param menuTexts + * @return + */ + private ContextMenu initChatMemberTableContextMenu(ObservableList contextMenuEntries) { // new mechanic + + ContextMenu chatMemberContextMenu = new ContextMenu(); + + for (Iterator iterator = contextMenuEntries.iterator(); iterator.hasNext();) { + String string = (String) iterator.next(); + final MenuItem menuItem = new MenuItem(string); + menuItem.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + menuItem.getText()); + } + }); + + chatMemberContextMenu.getItems().add(menuItem); + + } + +// MenuItem macro1 = new MenuItem("Pse Sked?"); +// macro1.setOnAction(new EventHandler() { +// public void handle(ActionEvent event) { +// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + macro1.getText()); +// } +// }); +// MenuItem macro10 = new MenuItem("Pse qrg 2m?"); +// MenuItem macro20 = new MenuItem("Pse Call at "); +// MenuItem macro30 = new MenuItem("In qso nw, pse qrx, I will meep you"); +// MenuItem macro40 = new MenuItem("Pse qrg 70cm?"); +// MenuItem macro50 = new MenuItem("pse qrg 23cm?"); +// MenuItem macro60 = new MenuItem("____________________________________"); +// MenuItem macro70 = new MenuItem("Watch QSO history"); +// +// chatMemberContextMenu.getItems().add(macro1); +// chatMemberContextMenu.getItems().add(macro10); +// chatMemberContextMenu.getItems().add(macro20); +// chatMemberContextMenu.getItems().add(macro30); +// chatMemberContextMenu.getItems().add(macro40); +// chatMemberContextMenu.getItems().add(macro50); +// chatMemberContextMenu.getItems().add(macro60); +// chatMemberContextMenu.getItems().add(macro70); + + return chatMemberContextMenu; + + } + + /** + * initializes the tableview in which the cq- and beacon-texts are shown + * + * @return + */ + private TableView initChatGeneralMSGTable() { + + TableView tbl_generalMSGTable = new TableView(); + tbl_generalMSGTable.setTooltip(new Tooltip("General messages are shown here (handle it like CQ messages)")); + + TableColumn timeCol = new TableColumn("Time"); + timeCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty time = new SimpleStringProperty(); + + time.setValue(new Utils4KST() + .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime())); + + return time; + } + }); + + TableColumn callSignCol = new TableColumn("Callsign"); + callSignCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callSign = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign()); + } else { + + callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callSign; + } + }); + + TableColumn nameCol = new TableColumn("Name"); + nameCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty name = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + name.setValue(cellDataFeatures.getValue().getSender().getName()); + } else { + + name.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return name; + } + }); + + TableColumn qrgCol = new TableColumn("Last QRG"); + qrgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + StringProperty qrg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + +// qrg.setValue(cellDataFeatures.getValue().getSender().getFrequency()); + qrg = cellDataFeatures.getValue().getSender().getFrequency(); + } else { + + qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qrg; + } + }); + + TableColumn msgCol = new TableColumn("Message"); + msgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty msg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getMessageText() != null) { + + msg.setValue(cellDataFeatures.getValue().getMessageText()); + } else { + + msg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return msg; + } + }); + msgCol.prefWidthProperty().bind(tbl_generalMSGTable.widthProperty().divide(2)); + + msgCol.setCellFactory(new Callback, TableCell>() { + public TableCell call(TableColumn param) { + return new TableCell() { + + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (!isEmpty()) { + this.setTextFill(Color.BLACK); + // Get fancy and change color based on data + if (item.toUpperCase() + .contains(chatcontroller.getChatPreferences().getLoginCallSign().toUpperCase())) { + this.setTextFill(Color.GREEN); + } + setText(item); + } + } + }; + } + }); + + tbl_generalMSGTable.getColumns().addAll(timeCol, callSignCol, nameCol, msgCol, qrgCol); + + ObservableList generalMSGList = chatcontroller.getLst_toAllMessageList(); + tbl_generalMSGTable.setItems(generalMSGList); + + return tbl_generalMSGTable; + } + + private TableView initChatprivateMSGTable() { + + TableView tbl_privateMSGTable = new TableView(); + tbl_privateMSGTable.setTooltip(new Tooltip("Private messages to you are shown here")); + + TableColumn timeCol = new TableColumn("Time"); + timeCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty time = new SimpleStringProperty(); + + time.setValue(new Utils4KST() + .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime())); + + return time; + } + }); + + TableColumn callSignCol = new TableColumn("Callsign"); + callSignCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callSign = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign()); + } else { + + callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callSign; + } + }); + + callSignCol.setCellFactory(new Callback, TableCell>() { + public TableCell call(TableColumn param) { + return new TableCell() { + + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (!isEmpty()) { + this.setTextFill(Color.BLACK); + // Get fancy and change color based on data + if (item.contains(chatcontroller.getChatPreferences().getLoginCallSign())) { + this.setTextFill(Color.GREEN); + +// AudioClip sound = new AudioClip(getClass().getResource("/K.mp3").toExternalForm()); +// sound.play(); + + } + setText(item); + } + } + }; + } + }); + + TableColumn nameCol = new TableColumn("Name"); + nameCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty name = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + name.setValue(cellDataFeatures.getValue().getSender().getName()); + } else { + + name.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return name; + } + }); + + TableColumn qraCol = new TableColumn("QRA"); + qraCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty qra = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + qra.setValue(cellDataFeatures.getValue().getSender().getQra()); + } else { + + qra.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qra; + } + }); + + TableColumn qrgCol = new TableColumn("Last known QRG"); + qrgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + StringProperty qrg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + +// qrg.setValue(cellDataFeatures.getValue().getSender().getFrequency()); + qrg = cellDataFeatures.getValue().getSender().getFrequency(); + } else { + + qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qrg; + } + }); + + TableColumn msgCol = new TableColumn("Message"); + msgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty msg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getMessageText() != null) { + + msg.setValue(cellDataFeatures.getValue().getMessageText()); + } else { + + msg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return msg; + } + }); + msgCol.prefWidthProperty().bind(tbl_privateMSGTable.widthProperty().divide(2.5)); + + TableColumn airScoutCol = new TableColumn("AP [minutes / pot%]"); + airScoutCol.setCellValueFactory(new Callback, ObservableValue>() { + + boolean isnull =false; + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty airPlaneInfo = new SimpleStringProperty(); + + try { + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes(); + } catch (NullPointerException e) { + airPlaneInfo.setValue(" "); + isnull = true; + } + +// if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() == null) { +// airPlaneInfo.setValue(" "); +// } + +// else + try { + if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() + .size() <= 0) { + airPlaneInfo.setValue(" ");} + + } catch (NullPointerException e) { + airPlaneInfo.setValue(" "); + isnull = true; + } +// if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() +// .size() <= 0) { +// airPlaneInfo.setValue(" "); +// } + +// else + if (!isnull) { + String apInfoText = "" + + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() + .get(0).getArrivingDurationMinutes() + + " (" + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo() + .getRisingAirplanes().get(0).getPotential() + + "%)"; +// +// + if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() + .size() > 1) { + apInfoText += " / " + + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() + .get(1).getArrivingDurationMinutes() + + " (" + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo() + .getRisingAirplanes().get(1).getPotential() + + "%)"; + } + + airPlaneInfo.setValue(apInfoText); + } else { + airPlaneInfo.setValue(" "); //no planes rising + } + + return airPlaneInfo; + } + }); + /** + * HIGH EXPERIMENTAL:::::::: + */ + airScoutCol.setCellFactory(new Callback, TableCell>() { + public TableCell call(TableColumn param) { + return new TableCell() { + + @Override + public void updateItem(String item, boolean empty) { + super.updateItem(item, empty); + if (!isEmpty()) { + this.setTextFill(Color.BLACK); + // Get fancy and change color based on data + if (item.contains("100%")) { + this.setTextFill(Color.BLUEVIOLET); + } else if (item.contains("75%") && !item.contains("100%")) { + this.setTextFill(Color.RED); + } else if (item.contains("50%") && ((!item.contains("100%")) || (!item.contains("75%")))) { + this.setTextFill(Color.ORANGE); + } + + setText(item); + } + } + }; + } + }); + /** + * END HIGH EXPERIMENTAL:::::::: + */ + + tbl_privateMSGTable.getColumns().addAll(timeCol, callSignCol, nameCol, qraCol, msgCol, qrgCol, airScoutCol); + + ObservableList privateMSGList = chatcontroller.getLst_toMeMessageList(); + tbl_privateMSGTable.setItems(privateMSGList); + + return tbl_privateMSGTable; + } + + private TableView initDXClusterTable() { + + TableView tbl_DXCTable = new TableView(); + tbl_DXCTable.setTooltip(new Tooltip("Cluster Messages are shown here")); + + TableColumn timeCol = new TableColumn("Time"); + timeCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty time = new SimpleStringProperty(); + + time.setValue( + new Utils4KST().time_convertEpochToReadable(cellDataFeatures.getValue().getTimeGenerated())); + + return time; + } + }); + + TableColumn callSignCol = new TableColumn("Call tx"); + callSignCol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callSign = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign()); + } else { + + callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callSign; + } + }); + + TableColumn locTXCol = new TableColumn("LOC tx"); + locTXCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty locTX = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + locTX.setValue(cellDataFeatures.getValue().getSender().getQra()); + } else { + + locTX.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return locTX; + } + }); + + TableColumn callSignRXCol = new TableColumn("Call rx"); + callSignRXCol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callSignRX = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getReceiver() != null) { + + callSignRX.setValue(cellDataFeatures.getValue().getReceiver().getCallSign()); + } else { + + callSignRX.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callSignRX; + } + }); + + TableColumn locRXCol = new TableColumn("LOC rx"); + locRXCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty locRX = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + locRX.setValue(cellDataFeatures.getValue().getReceiver().getQra()); + } else { + + locRX.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return locRX; + } + }); + + TableColumn qrgCol = new TableColumn("QRG"); + qrgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + StringProperty qrg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getReceiver() != null) { + +// qrg.setValue(cellDataFeatures.getValue().getReceiver().getFrequency()); + qrg = cellDataFeatures.getValue().getReceiver().getFrequency(); + } else { + + qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qrg; + } + }); + + TableColumn msgCol = new TableColumn("Message"); + msgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty msg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getMessageInhibited() != null) { + + msg.setValue(cellDataFeatures.getValue().getMessageInhibited()); + } else { + + msg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return msg; + } + }); + + TableColumn workedCol = new TableColumn("wkd"); + workedCol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + wkd.setValue(cellDataFeatures.getValue().isReceiverWkd() + ""); + + if (cellDataFeatures.getValue().isReceiverWkd()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + tbl_DXCTable.getColumns().addAll(timeCol, callSignCol, locTXCol, callSignRXCol, locRXCol, qrgCol, msgCol, + workedCol); + + ObservableList clusterMSGList = chatcontroller.getLst_clusterMemberList(); + tbl_DXCTable.setItems(clusterMSGList); + + return tbl_DXCTable; + } + + private TableView initChatToOtherMSGTable() { + + TableView tbl_toOtherMSGTable = new TableView(); + tbl_toOtherMSGTable.setTooltip(new Tooltip("Messages between other member are shown here")); + + TableColumn timeCol = new TableColumn("Time"); + timeCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty time = new SimpleStringProperty(); + + time.setValue(new Utils4KST() + .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime())); + + return time; + } + }); + + TableColumn callSignTRCVCol = new TableColumn("Call TX"); + callSignTRCVCol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callSign = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign()); + } else { + + callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callSign; + } + }); + + TableColumn callSignRCVRCol = new TableColumn("Call RX"); + callSignRCVRCol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callTX = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getReceiver().getCallSign() != null) { + + callTX.setValue(cellDataFeatures.getValue().getReceiver().getCallSign()); + } else { + + callTX.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return callTX; + } + }); + + TableColumn nameCol = new TableColumn("Name"); + nameCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty name = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + + name.setValue(cellDataFeatures.getValue().getSender().getName()); + } else { + + name.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return name; + } + }); + + TableColumn qrgTXerCol = new TableColumn("Last QRG TX"); + qrgTXerCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + StringProperty qrg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender() != null) { + +// qrg.setValue(cellDataFeatures.getValue().getSender().getFrequency()); + qrg = cellDataFeatures.getValue().getSender().getFrequency(); + } else { + + qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qrg; + } + }); + + TableColumn qrgRXerCol = new TableColumn("Last QRG RX"); + qrgRXerCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + StringProperty qrg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getReceiver() != null) { + +// qrg.setValue(cellDataFeatures.getValue().getReceiver().getFrequency()); + qrg = cellDataFeatures.getValue().getReceiver().getFrequency(); + + } else { + + qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return qrg; + } + }); + + TableColumn msgCol = new TableColumn("Message"); + msgCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty msg = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getMessageText() != null) { + + msg.setValue(cellDataFeatures.getValue().getMessageText()); + } else { + + msg.setValue("");// TODO: Prevents a bug of not setting all values as a default + } + return msg; + } + }); + msgCol.prefWidthProperty().bind(tbl_toOtherMSGTable.widthProperty().divide(2)); + + TableColumn workedRXCol = new TableColumn("wkd RX?"); + workedRXCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getReceiver().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + TableColumn workedTXCol = new TableColumn("wkd TX?"); + workedRXCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().getSender().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + tbl_toOtherMSGTable.getColumns().addAll(timeCol, callSignTRCVCol, qrgTXerCol, workedTXCol, callSignRCVRCol, + qrgRXerCol, workedRXCol, nameCol, msgCol); + + ObservableList toOtherMSGList = chatcontroller.getLst_toOtherMessageList(); + tbl_toOtherMSGTable.setItems(toOtherMSGList); + + return tbl_toOtherMSGTable; + } + + private TableView initShortcutTable() { + + TableView tbl_txtShorts = new TableView(); + tbl_txtShorts.setTooltip(new Tooltip("Personalize your shortcut-buttons here")); + + TableColumn ShortCol = new TableColumn("Shortcut-Buttontext"); + ShortCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty shortCT = new SimpleStringProperty(); + shortCT.setValue(cellDataFeatures.getValue()); + return shortCT; + } + }); + ShortCol.setCellFactory(TextFieldTableCell.forTableColumn()); + + ShortCol.setOnEditCommit(new EventHandler>() { + @Override + public void handle(CellEditEvent t) { + + String newValue = t.getNewValue(); + t.getTableView().getItems().set(t.getTablePosition().getRow(), newValue); + + if (newValue == "") { // delete lines which had been cleared + t.getTableView().getItems().remove(t.getTablePosition().getRow()); + } + + flwPane_textSnippets.getChildren().clear(); + flwPane_textSnippets.getChildren() + .addAll(buttonFactory(chatcontroller.getChatPreferences().getLst_txtShortCutBtnList())); + +//TODO: redraw panel +// chatMessageContextMenu = initChatMemberTableContextMenu(chatcontroller.getChatPreferences().getLst_txtSnipList()); // TODO: thats not +// // clean, there had +// // to be a listener +// // triggered update +// // method +// chatMemberContextMenu = initChatMemberTableContextMenu(chatcontroller.getChatPreferences().getLst_txtSnipList()); + + } + }); + + tbl_txtShorts.getColumns().addAll(ShortCol); + + tbl_txtShorts.setEditable(true); +// tbl_txtSnips.set + +// ObservableList lst_textSnipList = ); + tbl_txtShorts.setItems(chatcontroller.getChatPreferences().getLst_txtShortCutBtnList()); +// tbl_txtSnips.bind + + return tbl_txtShorts; + } // TODO: Textsnippets table + + private TableView initTextSnippetsTable() { + + TableView tbl_txtSnips = new TableView(); + tbl_txtSnips.setTooltip(new Tooltip("Personalize your textsnippets here")); + +// TableColumn idCol = new TableColumn("Index"); +// idCol.setCellValueFactory(new Callback, ObservableValue>() { +// +// @Override +// public ObservableValue call(CellDataFeatures cellDataFeatures) { +// int index = 0; +// +//// index.setValue(cellDataFeatures.getValue().); +// +// return (index); +// } +// }); + + TableColumn snipCol = new TableColumn("Snippet"); + snipCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty snippet = new SimpleStringProperty(); + snippet.setValue(cellDataFeatures.getValue()); + return snippet; + } + }); + snipCol.setCellFactory(TextFieldTableCell.forTableColumn()); + // TODO: https://www.youtube.com/watch?v=M_kp20qrtLw = tutorial dafuer + +// snipCol.setOnEditCommit(e->e.getTableView().getItems().get(e.getTablePosition().getRow()).replace(".*", e.getNewValue())); + + snipCol.setOnEditCommit(new EventHandler>() { + @Override + public void handle(CellEditEvent t) { + + String newValue = t.getNewValue(); + t.getTableView().getItems().set(t.getTablePosition().getRow(), newValue); + + if (newValue == "") { // delete lines which had been cleared + t.getTableView().getItems().remove(t.getTablePosition().getRow()); + } + + chatMessageContextMenu = initChatMemberTableContextMenu( + chatcontroller.getChatPreferences().getLst_txtSnipList()); // TODO: thats not + // clean, there had + // to be a listener + // triggered update + // method + chatMemberContextMenu = initChatMemberTableContextMenu( + chatcontroller.getChatPreferences().getLst_txtSnipList()); + + } + }); + + tbl_txtSnips.getColumns().addAll(snipCol); + + tbl_txtSnips.setEditable(true); +// tbl_txtSnips.set + +// ObservableList lst_textSnipList = ); + tbl_txtSnips.setItems(chatcontroller.getChatPreferences().getLst_txtSnipList()); +// tbl_txtSnips.bind + + return tbl_txtSnips; + } + + private TableView initWkdStnTable() { + + TableView tbl_chatMemberWkdDBTable = new TableView(); + tbl_chatMemberWkdDBTable.setTooltip(new Tooltip("worked info DB")); + + TableColumn callSignCol = new TableColumn("Callsign"); + callSignCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty callsgn = new SimpleStringProperty(); + + callsgn.setValue(cellDataFeatures.getValue().getCallSign()); + + return callsgn; + } + }); + + TableColumn workedCol = new TableColumn("worked"); + workedCol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + TableColumn wkdAny_subcol = new TableColumn("wkd"); + wkdAny_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + wkdAny_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(28)); + + TableColumn vhfCol_subcol = new TableColumn("144"); + vhfCol_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked144()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + vhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(28)); + + TableColumn uhfCol_subcol = new TableColumn("432"); + uhfCol_subcol + .setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked432()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + uhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(28)); + + TableColumn shf23_subcol = new TableColumn("23"); + shf23_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked1240()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf23_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(30)); + + TableColumn shf13_subcol = new TableColumn("13"); + shf13_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked2300()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf13_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(30)); + + TableColumn shf9_subcol = new TableColumn("9"); + shf9_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked3400()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf9_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(32)); + + TableColumn shf6_subcol = new TableColumn("6"); + shf6_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked5600()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + shf6_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(32)); + + TableColumn shf3_subcol = new TableColumn("3"); + shf3_subcol.setCellValueFactory(new Callback, ObservableValue>() { + + @Override + public ObservableValue call(CellDataFeatures cellDataFeatures) { + SimpleStringProperty wkd = new SimpleStringProperty(); + + if (cellDataFeatures.getValue().isWorked10G()) { + wkd.setValue("X"); + } else { + wkd.setValue(""); + } + + return wkd; + } + }); + + shf3_subcol.prefWidthProperty().bind(tbl_chatMemberWkdDBTable.widthProperty().divide(32)); + + workedCol.getColumns().addAll(wkdAny_subcol, vhfCol_subcol, uhfCol_subcol, shf23_subcol, shf13_subcol, + shf9_subcol, shf6_subcol, shf3_subcol); // TODO: automatize enabling to users bandChoice + + tbl_chatMemberWkdDBTable.getColumns().addAll(callSignCol, workedCol); + + tbl_chatMemberWkdDBTable.setItems(chatcontroller.getLst_DBBasedWkdCallSignList()); + + // TODO: https://www.youtube.com/watch?v=M_kp20qrtLw = tutorial dafuer + +// snipCol.setOnEditCommit(e->e.getTableView().getItems().get(e.getTablePosition().getRow()).replace(".*", e.getNewValue())); + +// callSignCol.setOnEditCommit(new EventHandler>() { +// @Override +// public void handle(CellEditEvent t) { +// +// String newValue = t.getNewValue(); +// t.getTableView().getItems().set(t.getTablePosition().getRow(), newValue); +// +// if (newValue == "") { //delete lines which had been cleared +// t.getTableView().getItems().remove(t.getTablePosition().getRow()); +// } +// +// chatMessageContextMenu = initChatMemberTableContextMenu(chatcontroller.getChatPreferences().getLst_txtSnipList()); // TODO: thats not +// // clean, there had +// // to be a listener +// // triggered update +// // method +// chatMemberContextMenu = initChatMemberTableContextMenu(chatcontroller.getChatPreferences().getLst_txtSnipList()); +// +// } +// }); + +// tbl_chatMemberWkdDBTable.getColumns().addAll(callSignCol); + + tbl_chatMemberWkdDBTable.setEditable(true); +// tbl_txtSnips.set + +// ObservableList lst_textSnipList = ); +// tbl_wkdStn.setItems(chatcontroller.getChatPreferences().getLst_txtSnipList()); +// tbl_txtSnips.bind + + return tbl_chatMemberWkdDBTable; + } + + private MenuBar initMenuBar() { + + Menu fileMenu = new Menu("File"); + + // create menuitems + MenuItem m1 = new MenuItem("Disconnect"); + m1.setDisable(true); + + MenuItem m10 = new MenuItem("Exit + disconnect"); + m10.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + closeWindowEvent(null); + } + }); + + // add menu items to menu + fileMenu.getItems().add(m1); + fileMenu.getItems().add(m10); + + Menu optionsMenu = new Menu("Options"); + MenuItem options1 = new MenuItem("Set QRG as name in Chat"); + MenuItem options10 = new MenuItem("Show options"); + options10.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + if (settingsStage.isShowing()) { + settingsStage.hide(); + } else { + settingsStage.show(); + } + } + }); + + optionsMenu.getItems().addAll(options1, options10); + + Menu macroMenu = new Menu("Macros"); + + MenuItem macro1 = new MenuItem("Pse Sked?"); + MenuItem macro10 = new MenuItem("Pse qrg 2m?"); + MenuItem macro20 = new MenuItem("Pse Call at "); + MenuItem macro30 = new MenuItem("In qso nw, pse qrx, I will meep you"); + MenuItem macro40 = new MenuItem("Pse qrg 70cm?"); + MenuItem macro50 = new MenuItem("pse qrg 23cm?"); + + macroMenu.getItems().addAll(macro1, macro10, macro20, macro30, macro40, macro50); + + Menu windowMenu = new Menu("Windows"); + MenuItem window1 = new MenuItem("Hide cluster / stranger QSOs"); + window1.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + if (clusterAndQSOMonStage.isShowing()) { + clusterAndQSOMonStage.hide(); + window1.setText("Show cluster / stranger QSOs"); + } else { + clusterAndQSOMonStage.show(); + window1.setText("Hide cluster / stranger QSOs"); + } + } + }); + MenuItem window20 = new MenuItem("hide options"); + window20.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + if (settingsStage.isShowing()) { + window20.setText("show options"); + settingsStage.hide(); + } else { + settingsStage.show(); + window20.setText("hide options"); + } + } + }); + + windowMenu.getItems().addAll(window1, window20); + + Menu helpMenu = new Menu("Info"); + + MenuItem help1 = new MenuItem("No help here."); + MenuItem help2 = new MenuItem("Support the chatclient development via PayPal"); + MenuItem help3 = new MenuItem("_______________________"); + help3.setDisable(true); + MenuItem help4 = new MenuItem("Visit DARC X08-Homepage"); + MenuItem help5 = new MenuItem("_______________________"); + help5.setDisable(true); + MenuItem help6 = new MenuItem("Contact the author using default mail app"); + MenuItem help8 = new MenuItem("Join kst4Contest newsgroup"); + MenuItem help9 = new MenuItem("Download the changelog / roadmap"); + + // Changelog + // https://e.pcloud.link/publink/show?code=XZwAoWZIap9DYqDlhhwncqAxLbU6STOh2PV + + help2.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + getHostServices().showDocument("https://www.paypal.com/paypalme/do5amf"); + +// Alert a = new Alert(AlertType.INFORMATION); +// +// a.setTitle("About this software"); +// a.setHeaderText("Who made it and how can you support it?"); +// a.setContentText(chatcontroller.getChatPreferences().getProgramVersion()); +// a.show(); + } + }); + + help4.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + getHostServices().showDocument("http://www.x08.de"); + +// Alert a = new Alert(AlertType.INFORMATION); +// +// a.setTitle("About this software"); +// a.setHeaderText("Who made it and how can you support it?"); +// a.setContentText(chatcontroller.getChatPreferences().getProgramVersion()); +// a.show(); + } + }); + + help6.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + getHostServices().showDocument("mailto:praktimarc+kst4contest@gmail.com"); + + } + }); + + help8.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + getHostServices().showDocument("https://groups.google.com/g/kst4contest/about"); + + } + }); + + help9.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + getHostServices() + .showDocument("https://e.pcloud.link/publink/show?code=XZwAoWZIap9DYqDlhhwncqAxLbU6STOh2PV"); + + } + }); + + MenuItem help10 = new MenuItem("About..."); + help10.setOnAction(new EventHandler() { + public void handle(ActionEvent event) { + + Alert a = new Alert(AlertType.INFORMATION); + + a.setTitle("About kst4contest"); + a.setHeaderText("ON4KST Chatclient by DO5AMF"); + a.setContentText(chatcontroller.getChatPreferences().getProgramVersion()); + a.show(); + } + }); + +// helpMenu.getItems().add(help1); + helpMenu.getItems().addAll(help2, help4, help5, help6, help8, help9, help10); + +// helpMenu.getItems().add(help2); +// helpMenu.getItems().add(help4); +// +// helpMenu.getItems().add(help10); + + MenuBar menubar = new MenuBar(); + menubar.getMenus().addAll(fileMenu, optionsMenu, windowMenu, helpMenu); // macromenu deleted + + return menubar; + + } + + TextField txt_chatMessageUserInput = new TextField(); + TextField txt_ownqrg = new TextField(); + TextField txt_myQTF = new TextField(); + Button btnOptionspnlConnect; + ContextMenu chatMessageContextMenu; // public due need to update it on modify + ContextMenu chatMemberContextMenu;// public due need to update it on modify + FlowPane flwPane_textSnippets; + + Stage clusterAndQSOMonStage; + + Stage settingsStage; + + /** + * Generates buttons out of pre made Strings, one button per given string in the + * buttontext-array. Buttonclick will add the buttontext + " " to the + * send-Textfield
+ *
+ * + * ATTENTION: MYQRG-Button adds myqrg-textfield-string.
+ * For identification of the button in the dom and make it functional, the + * init-value have to be "MYQRG"!
+ * + * @param buttonText + * @return + */ + private Node[] buttonFactory(ObservableList shortcuts) { + + Button[] txMessageButtons = new Button[shortcuts.size()]; + + for (int i = 0; i < shortcuts.size(); i++) { + + txMessageButtons[i] = new Button(shortcuts.get(i)); + + if (shortcuts.get(i).equals("MYQRG")) { + txMessageButtons[i].setTooltip(new Tooltip("MYQRG")); + txMessageButtons[i] + .setStyle("-fx-background-color:\r\n" + " linear-gradient(#c8fac0, #c8fac0),\r\n" + + " radial-gradient(center 50% -40%, radius 200%, #c8ee36 45%, #c0c800 50%);\r\n" + + " -fx-background-radius: 6, 5;\r\n" + " -fx-background-insets: 0, 1;\r\n" + + " -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.4) , 5, 0.0 , 0 , 1 );\r\n" + + " -fx-text-fill: #395306"); + MYQRGButton = txMessageButtons[i]; + + } + + if (shortcuts.get(i).equals("/SETNAME MYQRG")) { +// txMessageButtons[i].setTooltip(new Tooltip("Set your qrg as name in Chat")); + txMessageButtons[i] + .setStyle("-fx-background-color:\r\n" + " linear-gradient(#c8fac0, #c8fac0),\r\n" + + " radial-gradient(center 50% -40%, radius 200%, #c8ee36 45%, #c0c800 50%);\r\n" + + " -fx-background-radius: 6, 5;\r\n" + " -fx-background-insets: 0, 1;\r\n" + + " -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.4) , 5, 0.0 , 0 , 1 );\r\n" + + " -fx-text-fill: #395306"); + MYCALLSetQRGButton = txMessageButtons[i]; + } + + txMessageButtons[i].setOnAction(new EventHandler() { + + @Override + public void handle(ActionEvent arg0) { + + if (((Button) arg0.getSource()).getText().equals("MYQRG")) { + ((Button) arg0.getSource()).setTooltip(new Tooltip("MYQRG")); + + } + + if (((Button) arg0.getSource()).getTooltip() != null) { + + if (((Button) arg0.getSource()).getText().equals("MYQRG") + || ((Button) arg0.getSource()).getTooltip().getText().equals("MYQRG")) { + +// ((Button) arg0.getSource()).setText(txt_ownqrg.getText()); + ((Button) arg0.getSource()).setTooltip(new Tooltip("MYQRG")); + + if (((Button) arg0.getSource()).getTooltip().getText().equals("MYQRG")) { +// ((Button) arg0.getSource()).setText(txt_ownqrg.getText()); + txt_chatMessageUserInput + .setText(txt_chatMessageUserInput.getText() + txt_ownqrg.getText() + " "); + } + } + } else { + +// System.out.println("Button clicked " + ((Button) arg0.getSource()).getText()); + txt_chatMessageUserInput.setText( + txt_chatMessageUserInput.getText() + ((Button) arg0.getSource()).getText() + " "); + + } + + } + }); + } + + return txMessageButtons; + } + + @Override + public void stop() { + System.out.println("[Main.java, Info:] Stage is closing, killing all resources"); + timer_buildWindowTitle.purge(); + timer_buildWindowTitle.cancel(); + + timer_chatMemberTableSortTimer.purge(); + timer_chatMemberTableSortTimer.cancel(); + + timer_updatePrivatemessageTable.purge(); + timer_updatePrivatemessageTable.cancel(); + chatcontroller.disconnect("CLOSEALL"); + +// Platform.exit(); + + } + + @Override + public void start(Stage primaryStage) throws InterruptedException, IOException { +// this.primaryStage = primaryStage; +// ChatCategory category = new ChatCategory(0); //TODO: get the Category out of the preferences-object + + ChatMember ownChatMemberObject = new ChatMember(); +// ownChatMemberObject.setCallSign("DM5M"); +// ownChatMemberObject.setPassword("antennen"); +// ownChatMemberObject.setName("QRO 15dBd"); +// ownChatMemberObject.setQra("JO51IJ"); + + chatcontroller = new ChatController(ownChatMemberObject); // instantiate the Chatcontroller with the user object +// chatcontroller.execute(); //TODO:THAT IS THE MAIN POINT WHERE THE CHAT WILL BE STARTED --- MOVED TO CONNECT BUTTON EVENTHANDLER + +// System.out.println(chatcontroller.getChatMemberTable().size()); + + try { + txt_ownqrg.setStyle("-fx-text-inner-color: #BA55D3;"); + + txt_ownqrg.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + System.out.println( + "[Main.java, Info]: Set the frequency property by hand to: " + txt_ownqrg.getText()); +// chatcontroller.getChatPreferences().setMYQRG(txt_ownqrg.getText()); + chatcontroller.getChatPreferences().getMYQRG().set(txt_ownqrg.getText()); + ; +// MYQRGButton.setText(txt_ownqrg.getText()); + } + } + }); + + txt_myQTF.setStyle("-fx-text-inner-color: #BA55D3;"); + + txt_myQTF.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + System.out.println( + "[Main.java, Info]: Set the MYQTF property by hand to: " + txt_myQTF.getText()); + chatcontroller.getChatPreferences().getActualQTF().set(Integer.parseInt(txt_myQTF.getText())); + } + } + }); + + txt_myQTF.setPrefSize(40, 0); +// txt_ownqrg.setMinSize(40, 0); + txt_myQTF.setAlignment(Pos.BASELINE_RIGHT); + txt_myQTF.setTooltip(new Tooltip("Enter/update your actual qtf here for using path suggestions")); + + SplitPane mainWindowLeftSplitPane = new SplitPane(); + mainWindowLeftSplitPane.setOrientation(Orientation.HORIZONTAL); + + BorderPane bPaneChatWindow = new BorderPane(); + + Scene scene = new Scene(bPaneChatWindow, 1024, 768); + +// primaryStage.setTitle(this.chatcontroller.getChatPreferences().getChatState()); + +// scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); + + MenuBar mainScreenMenuBar = initMenuBar(); + bPaneChatWindow.setTop(mainScreenMenuBar); + +// bPaneChatWindow.setLeft(new Label("This will be at the left")); + +// bPaneChatWindow.setRight(scrollabeUserListPanel); + + SplitPane messageSectionSplitpane = new SplitPane(); + messageSectionSplitpane.setOrientation(Orientation.VERTICAL); + + HBox textInputFlowPane = new HBox(); + +// FlowPane textInputFlowPane = new FlowPane(); + + Button sendButton = new Button("send"); + sendButton.setMinSize(60, 0); + sendButton.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + ChatMessage sendMe = new ChatMessage(); + sendMe.setMessageText(txt_chatMessageUserInput.getText()); + sendMe.setMessageDirectedToServer(false); + + chatcontroller.getMessageTXBus().add(sendMe); + + txt_chatMessageUserInput.clear(); + + } + }); + + Button btn_clear = new Button("clear"); + btn_clear.setMinSize(60, 0); + btn_clear.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { +// System.out.println("clear clicked: " + event.toString()); + txt_chatMessageUserInput.clear(); + + } + }); + +// TextField txt_chatMessageUserInput +// txt_chatMessageUserInput.setPrefWidth("80%"); + txt_chatMessageUserInput.setPrefSize(500, 0); + txt_chatMessageUserInput.setText(""); + txt_chatMessageUserInput.setTooltip(new Tooltip("Textmessage to Chat")); + txt_chatMessageUserInput.setOnKeyPressed(new EventHandler() { + + @Override + public void handle(KeyEvent event) { + if (event.getCode().equals(KeyCode.ENTER)) { +// System.out.println("Enter pressed"); + + ChatMessage sendMe = new ChatMessage(); + sendMe.setMessageText(txt_chatMessageUserInput.getText()); + sendMe.setMessageDirectedToServer(false); + + chatcontroller.getMessageTXBus().add(sendMe); + + txt_chatMessageUserInput.clear(); + } + } + }); + txt_chatMessageUserInput.textProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + + if (txt_chatMessageUserInput.getText().contains("MYQRG")) { + System.out.println("MYQRG erkannt"); + +// txt_chatMessageUserInput.getText().replaceAll("MYQRG", chatcontroller.getChatPreferences().getMYQRG()); +// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText().replaceAll("MYQRG", chatcontroller.getChatPreferences().getMYQRG())); + txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText().replaceAll("MYQRG", + chatcontroller.getChatPreferences().getMYQRG().getValue())); + } + ; + + if (txt_chatMessageUserInput.getText().contains("MYLOCATOR")) { + System.out.println("MYLOCATOR erkannt"); + +// txt_chatMessageUserInput.getText().replaceAll("MYQRG", chatcontroller.getChatPreferences().getMYQRG()); + txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText().replaceAll("MYLOCATOR", + chatcontroller.getChatPreferences().getLoginLocator())); + } + ; + } + }); + + final Separator sepVert1 = new Separator(); + sepVert1.setOrientation(Orientation.VERTICAL); + sepVert1.setValignment(VPos.CENTER); +// sepVert1.setPrefHeight(80); + sepVert1.setPrefWidth(30); + + txt_ownqrg.setText("MYQRG"); + txt_ownqrg.setPrefSize(80, 0); +// txt_ownqrg.setMinSize(40, 0); + txt_ownqrg.setAlignment(Pos.BASELINE_RIGHT); +// System.out.println(txt_ownqrg.textProperty(); + + primaryStage.setTitle(chatcontroller.getChatPreferences().getChatState()); + + timer_buildWindowTitle = new Timer(); + timer_buildWindowTitle.scheduleAtFixedRate(new TimerTask() { + public void run() { + + Thread.currentThread().setName("buildWindowTitleTimer"); + + Platform.runLater(() -> { + + String chatState = ""; + if (chatcontroller.isConnectedAndLoggedIn()) { + + chatState = "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + + " as " + chatcontroller.getChatPreferences().getLoginCallSign() + " (" + + chatcontroller.getChatPreferences().getLoginName() + ")" + " in " + + chatcontroller.getChatPreferences().getLoginLocator() + " (" + + chatcontroller.getLst_chatMemberList().size() + " users online.)," + + (chatcontroller.getLst_toAllMessageList().size() + + chatcontroller.getLst_toOtherMessageList().size() + + chatcontroller.getLst_toMeMessageList().size()) + + " messages total."; + chatcontroller.getChatPreferences().setChatState(chatState); + } + + else { + chatState = "DISCONNECTED, CHECK YOUR INTERNET-CONNECTION!"; + } + + primaryStage.setTitle(chatcontroller.getChatPreferences().getChatState()); + +// System.out.println(chatcontroller.getChatPreferences().getChatState()); + }); + } + }, new Date(), 5000); + + textInputFlowPane.getChildren().addAll(txt_chatMessageUserInput, sendButton, btn_clear, sepVert1, + txt_ownqrg, txt_myQTF); + +// HBox hbx_textSnippets = new HBox(); + + flwPane_textSnippets = new FlowPane(); + + flwPane_textSnippets.getChildren() + .addAll(buttonFactory(this.chatcontroller.getChatPreferences().getLst_txtShortCutBtnList())); + +// hbx_textSnippets.getChildren().add(flwPane_textSnippets); +// hbx_textSnippets.set + + TableView privateMessageTable = initChatprivateMSGTable(); +// +// ContextMenu chatMessageContextMenu = initChatMemberTableContextMenu( old mechanic +// this.chatcontroller.getChatPreferences().getTextSnippets()); + + chatMessageContextMenu = initChatMemberTableContextMenu( + this.chatcontroller.getChatPreferences().getLst_txtSnipList()); // new mechanic + + privateMessageTable.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { + + @Override + public void handle(MouseEvent t) { + if (t.getButton() == MouseButton.SECONDARY) { + chatMessageContextMenu.show(primaryStage, t.getScreenX(), t.getScreenY()); + + } + } + }); + + TableViewSelectionModel privateChatselectionModelChatMessage = privateMessageTable + .getSelectionModel(); + privateChatselectionModelChatMessage.setSelectionMode(SelectionMode.SINGLE); + +// tbl_chatMember.getda + + ObservableList selectedChatMessageList = privateChatselectionModelChatMessage + .getSelectedItems(); + selectedChatMessageList.addListener(new ListChangeListener() { + @Override + public void onChanged(Change selectedChatMemberPrivateChat) { + if (privateChatselectionModelChatMessage.getSelectedItems().isEmpty()) { + // do nothing, that was a deselection-event! + } else { + + txt_chatMessageUserInput.clear(); + txt_chatMessageUserInput.setText("/cq " + + selectedChatMemberPrivateChat.getList().get(0).getSender().getCallSign() + " "); + System.out.println("privChat selected ChatMember: " + + selectedChatMemberPrivateChat.getList().get(0).getSender()); + // selectedChatMemberList.clear(); +// selectionModelChatMember.clearSelection(0); + } + } + }); + + timer_updatePrivatemessageTable = new Timer(); + timer_updatePrivatemessageTable.scheduleAtFixedRate(new TimerTask() { + + public void run() { + Thread.currentThread().setName("UpdatePrivateMessageTableTimer"); + Platform.runLater(() -> { + + privateMessageTable.refresh(); + + }); + } + }, new Date(), 5000); + + messageSectionSplitpane.getItems().addAll(privateMessageTable, flwPane_textSnippets, textInputFlowPane, + initChatGeneralMSGTable()); + + bPaneChatWindow.setCenter(mainWindowLeftSplitPane); + + TableView tbl_chatMember = new TableView(); + tbl_chatMember = initChatMemberTable(); + + TableViewSelectionModel selectionModelChatMember = tbl_chatMember.getSelectionModel(); + selectionModelChatMember.setSelectionMode(SelectionMode.SINGLE); + + tbl_chatMember.autosize(); + +// tbl_chatMember.getda + + ObservableList selectedChatMemberList = selectionModelChatMember.getSelectedItems(); + selectedChatMemberList.addListener(new ListChangeListener() { + @Override + public void onChanged(Change selectedChatMember) { + if (selectionModelChatMember.getSelectedItems().isEmpty()) { + // do nothing, that was a deselection-event! + } else { + + txt_chatMessageUserInput.clear(); + txt_chatMessageUserInput + .setText("/cq " + selectedChatMember.getList().get(0).getCallSign() + " "); + System.out.println( + "##################selected ChatMember: " + selectedChatMember.getList().get(0)); + // selectedChatMemberList.clear(); +// selectionModelChatMember.clearSelection(0); + } + } + }); + + // TODO: Take together contextmenu and macromenu, generate together + + // Creates the Contextmenu for right clicks to the chatmember-list + // TODO: If the old selection is identical with the new selection, /CQ station + // will not be written by the contextmenu clicklistener. Have to improve that + // some time +// ContextMenu chatMemberContextMenu = initChatMemberTableContextMenu( +// this.chatcontroller.getChatPreferences().getTextSnippets()); old mechanic + + chatMemberContextMenu = initChatMemberTableContextMenu( + this.chatcontroller.getChatPreferences().getLst_txtSnipList()); + + tbl_chatMember.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { + + @Override + public void handle(MouseEvent t) { + if (t.getButton() == MouseButton.SECONDARY) { + chatMemberContextMenu.show(primaryStage, t.getScreenX(), t.getScreenY()); + + } + } + }); + + mainWindowLeftSplitPane.getItems().addAll(messageSectionSplitpane, tbl_chatMember); + + primaryStage.setScene(scene); + + primaryStage.show(); + + } catch (Exception e) { + e.printStackTrace(); + } + + clusterAndQSOMonStage = new Stage(); +// clusterAndQSOMonStage.initStyle(StageStyle.UTILITY); + clusterAndQSOMonStage.setTitle("Cluster & QSO of the other"); + SplitPane pnl_directedMSGWin = new SplitPane(); + pnl_directedMSGWin.setOrientation(Orientation.VERTICAL); + + pnl_directedMSGWin.getItems().addAll(initDXClusterTable(), initChatToOtherMSGTable()); + + clusterAndQSOMonStage.setScene(new Scene(pnl_directedMSGWin, 700, 500)); + clusterAndQSOMonStage.show(); + + /***************************************************************************** + * + * Settings Scene + * + * + ****************************************************************************/ + settingsStage = new Stage(); + settingsStage.setTitle("Change Client seetings"); + + BorderPane optionsPanel = new BorderPane(); + + TabPane tabPaneOptions = new TabPane(); + + /************************************************************************************* + * + * Stations settings Tab in settings scene + * + *************************************************************************************/ + + GridPane grdPnlStation = new GridPane(); + grdPnlStation.setPadding(new Insets(10, 10, 10, 10)); + grdPnlStation.setVgap(5); + grdPnlStation.setHgap(5); + + Label lblCallSign = new Label("Login-Callsign:"); +// TextField txtFldCallSign = new TextField("dm5m"); + TextField txtFldCallSign = new TextField(this.chatcontroller.getChatPreferences().getLoginCallSign()); + + txtFldCallSign.textProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observed, String oldString, String newString) { + + System.out.println("[Main.java, Info]: Setted the Login Callsign: " + txtFldCallSign.getText()); + chatcontroller.getChatPreferences().setLoginCallSign(txtFldCallSign.getText()); + } + }); + + Label lblPassword = new Label("Login-Password:"); + PasswordField txtFldPassword = new PasswordField(); + txtFldPassword.setText(this.chatcontroller.getChatPreferences().getLoginPassword()); + txtFldPassword.textProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observed, String oldString, String newString) { + + System.out.println("[Main.java, Info]: Setted the Login password... "); + chatcontroller.getChatPreferences().setLoginPassword(txtFldPassword.getText()); + } + }); + + Label lblName = new Label("Name in Chat:"); + TextField txtFldName = new TextField(this.chatcontroller.getChatPreferences().getLoginName()); + + txtFldName.textProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observed, String oldString, String newString) { + + System.out.println("[Main.java, Info]: Setted the Login name: " + txtFldName.getText()); + chatcontroller.getChatPreferences().setLoginName(txtFldName.getText()); + } + }); + + Label lblLocator = new Label("Locator in Chat:"); + TextField txtFldLocator = new TextField(this.chatcontroller.getChatPreferences().getLoginLocator()); + + txtFldLocator.textProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observed, String oldString, String newString) { + + System.out.println("[Main.java, Info]: Setted the Login locator: " + txtFldLocator.getText()); + chatcontroller.getChatPreferences().setLoginLocator(txtFldLocator.getText()); + } + }); + + Label lblChatCategory = new Label("Chatcategory:"); + ChoiceBox choiceBxChatChategory = new ChoiceBox(); + ChatCategory chatCategoryChoice = new ChatCategory(0); + choiceBxChatChategory.setValue(this.chatcontroller.getChatPreferences().getLoginChatCategory()); + + for (int i = 0; i < chatCategoryChoice.getPossibleCategoryNumbers().length; i++) { + ChatCategory temp = new ChatCategory(i + 1); + choiceBxChatChategory.getItems().add(temp); + } + + choiceBxChatChategory.getSelectionModel().selectedItemProperty() + .addListener((ChangeListener) (ov, old, newval) -> { + ChatCategory idx = (ChatCategory) newval; + System.out.println("Changed Choice: " + + choiceBxChatChategory.getSelectionModel().selectedItemProperty().toString()); + this.chatcontroller.getChatPreferences() + .setLoginChatCategory(new ChatCategory(idx.getCategoryNumber())); + btnOptionspnlConnect.setText("Connect to " + choiceBxChatChategory.getSelectionModel() + .selectedItemProperty().get().getChatCategoryName( + choiceBxChatChategory.getSelectionModel().getSelectedItem().getCategoryNumber())); + +// this.chatcontroller.getChatPreferences().setLoginChatCategory(idx); + }); + +// choiceBxChatChategory.getItems().add("2"); //hard coded... +// choiceBxChatChategory.setValue("2"); //setting default value + +// HBox labeledSeparator = new HBox(); +// Label lblStationPanelInfo = new Label(); +// Separator leftSeparator = new Separator(); +// leftSeparator.setPrefWidth(100); +// Separator rightSeparator = new Separator(); +// rightSeparator.setPrefWidth(100); +// labeledSeparator.getChildren().add(leftSeparator); +// labeledSeparator.getChildren().add(lblStationPanelInfo); +// labeledSeparator.getChildren().add(rightSeparator); +// labeledSeparator.setAlignment(Pos.CENTER); + + grdPnlStation.add(lblCallSign, 0, 0); + grdPnlStation.add(txtFldCallSign, 1, 0); + grdPnlStation.add(lblPassword, 0, 1); + grdPnlStation.add(txtFldPassword, 1, 1); + grdPnlStation.add(lblName, 0, 2); + grdPnlStation.add(txtFldName, 1, 2); + grdPnlStation.add(lblLocator, 0, 3); + grdPnlStation.add(txtFldLocator, 1, 3); + grdPnlStation.add(lblChatCategory, 0, 4); + grdPnlStation.add(choiceBxChatChategory, 1, 4); + + VBox vbxStation = new VBox(); + vbxStation.setPadding(new Insets(10, 10, 10, 10)); + vbxStation.getChildren().addAll( + generateLabeledSeparator(100, "Set your Login Credentials and Station Parameters here"), grdPnlStation); + vbxStation.getChildren().addAll(generateLabeledSeparator(50, + "Don´t forget to reset the worked stations information before starting a new contest!")); + + /************************************************************************************* + * Log synch settings Tab + *************************************************************************************/ + + GridPane grdPnlLog = new GridPane(); + grdPnlLog.setPadding(new Insets(10, 10, 10, 10)); + grdPnlLog.setVgap(5); + grdPnlLog.setHgap(5); + + Label lblEnableFileBased = new Label("Use universal File based callsign Interpreter (readOnly!)"); + CheckBox chkBxEnableFileBasedInterpreterUCX = new CheckBox(); + chkBxEnableFileBasedInterpreterUCX + .setSelected(this.chatcontroller.getChatPreferences().isLogsynch_fileBasedWkdCallInterpreterEnabled()); + + chkBxEnableFileBasedInterpreterUCX.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { +// chk2.setSelected(!newValue); + chatcontroller.getChatPreferences().setLogsynch_fileBasedWkdCallInterpreterEnabled( + chkBxEnableFileBasedInterpreterUCX.isSelected()); + System.out.println("[Main.java, Info]: setted the file based worked-station-list to: " + + chatcontroller.getChatPreferences().isLogsynch_fileBasedWkdCallInterpreterEnabled()); + } + }); + + Label lblWkdInterpreterPathToFileTitle = new Label("Worked stations will be read there: "); + Label lblWkdInterpreterPathToFile = new Label( + this.chatcontroller.getChatPreferences().getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly()); + + Label lblUDPbyUCXLogBackupFilePathAndNameTitle = new Label("Backup UDP msgs to"); + Label lblUDPbyUCXLogBackupFilePathAndName = new Label( + this.chatcontroller.getChatPreferences().getLogSynch_storeWorkedCallSignsFileNameUDPMessageBackup()); + + Label lblEnableUDPbyUCX = new Label("Receive UCXLog network based UDP log messages"); + CheckBox chkBxEnableUCXLogUDPReceiver = new CheckBox(); + chkBxEnableUCXLogUDPReceiver + .setSelected(this.chatcontroller.getChatPreferences().isLogsynch_ucxUDPWkdCallListenerEnabled()); + chkBxEnableUCXLogUDPReceiver.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { +// chk2.setSelected(!newValue); + chatcontroller.getChatPreferences() + .setLogsynch_ucxUDPWkdCallListenerEnabled(chkBxEnableUCXLogUDPReceiver.isSelected()); + System.out.println("[Main.java, Info]: setted the udp worked-station receiver to: " + + chatcontroller.getChatPreferences().isLogsynch_ucxUDPWkdCallListenerEnabled()); + } + }); + + Label lblUDPByUCX = new Label("UDP-Port for message-listener (default is 12060)"); + TextField txtFldUDPPortforUCX = new TextField(""); + txtFldUDPPortforUCX + .setText(this.chatcontroller.getChatPreferences().getLogsynch_ucxUDPWkdCallListenerPort() + ""); + txtFldUDPPortforUCX.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + if (GuiUtils.isNumeric(txtFldUDPPortforUCX.getText())) { + + System.out.println("[Main.java, Info]: Set the ucx-listener port property by hand to: " + + txtFldUDPPortforUCX.getText()); +// chatcontroller.getChatPreferences().setMYQRG(txt_ownqrg.getText()); + chatcontroller.getChatPreferences() + .setLogsynch_ucxUDPWkdCallListenerPort(Integer.parseInt(txtFldUDPPortforUCX.getText())); +// MYQRGButton.setText(txt_ownqrg.getText()); + } else { + txtFldUDPPortforUCX.setText(txtFldUDPPortforUCX.getText() + " is an invalid Port"); + } + + } + } + }); + + HBox labeledSeparatorLogSynch = new HBox(); + + Button btn_changeFilePathAndName = new Button("Choose..."); + + btn_changeFilePathAndName.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + File filechooserSelectedfile; + + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Choose Readonly-Loginterpreter-File"); + fileChooser.setInitialDirectory( + new File(System.getProperty("user.home")) + ); + + try { + + filechooserSelectedfile = fileChooser.showOpenDialog(primaryStage); + + } catch (NullPointerException e) { + + filechooserSelectedfile = new File(chatcontroller.getChatPreferences().getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly()); + } + + System.out.println(filechooserSelectedfile.getAbsolutePath()); + + chatcontroller.getChatPreferences().setLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly(filechooserSelectedfile.getAbsolutePath()); + + lblWkdInterpreterPathToFile.setText(chatcontroller.getChatPreferences().getLogsynch_fileBasedWkdCallInterpreterFileNameReadOnly()); + + + } + }); + + + + + +// grdPnlLog.add(new Label("Settings for the file interpreter, which can interprete ASCII Callsigns out of all kinds of files by Patternmatching"), 0,0,1,1); + grdPnlLog.add(generateLabeledSeparator(100, "File polling for worked callsigns"), 0, 0, 2, 1); + grdPnlLog.add(lblEnableFileBased, 0, 1); + grdPnlLog.add(chkBxEnableFileBasedInterpreterUCX, 1, 1); + grdPnlLog.add(lblWkdInterpreterPathToFileTitle, 0, 2); + grdPnlLog.add(lblWkdInterpreterPathToFile, 1, 2); + grdPnlLog.add(btn_changeFilePathAndName, 2, 2); + grdPnlLog.add(generateLabeledSeparator(100, "N1MM/UCXLog/DXLog.net Network-Listener"), 0, 3, 2, 1); + grdPnlLog.add(lblEnableUDPbyUCX, 0, 4); + grdPnlLog.add(chkBxEnableUCXLogUDPReceiver, 1, 4); + grdPnlLog.add(lblUDPByUCX, 0, 5); + grdPnlLog.add(txtFldUDPPortforUCX, 1, 5); +// grdPnlLog.add(lblUDPbyUCXLogBackupFilePathAndNameTitle, 0, 6); removed due to db usage now +// grdPnlLog.add(lblUDPbyUCXLogBackupFilePathAndName, 1, 6); removed due to db usage now +// grdPnlLog.add(new Button("Change..."), 2, 6); removed due to db usage now + + VBox vbxLog = new VBox(); + vbxLog.setPadding(new Insets(10, 10, 10, 10)); + vbxLog.getChildren().addAll(grdPnlLog); + + /************************************************************************************* + * TRX synch settings Tab + *************************************************************************************/ + + GridPane grdPnltrx = new GridPane(); + grdPnltrx.setPadding(new Insets(10, 10, 10, 10)); + grdPnltrx.setVgap(5); + grdPnltrx.setHgap(5); + + Label lblEnableTRXMsgbyUCX = new Label("Receive UCXLog network based UDP trx messages at Port 12060"); + CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + chkBxEnableTRXMsgbyUCX + .setSelected(this.chatcontroller.getChatPreferences().isTrxSynch_ucxLogUDPListenerEnabled()); + + chkBxEnableTRXMsgbyUCX.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { +// chk2.setSelected(!newValue); + if (!newValue) { + chatcontroller.getChatPreferences() + .setTrxSynch_ucxLogUDPListenerEnabled(chkBxEnableTRXMsgbyUCX.isSelected()); + txt_ownqrg.textProperty().unbind(); + txt_ownqrg.setTooltip(new Tooltip("Your cq qrg will be updated by hand (watch prefs!)")); + System.out.println("[Main.java, Info]: MYQRG will be changed only by User input"); + System.out.println("[Main.java, Info]: setted the trx-frequency updated by ucxlog to: " + + chatcontroller.getChatPreferences().isTrxSynch_ucxLogUDPListenerEnabled()); + + } else { + chatcontroller.getChatPreferences() + .setTrxSynch_ucxLogUDPListenerEnabled(chkBxEnableTRXMsgbyUCX.isSelected()); + txt_ownqrg.textProperty().bind(chatcontroller.getChatPreferences().getMYQRG()); + txt_ownqrg.setTooltip(new Tooltip("Your cq qrg will be updated by the log program (watch prefs!)")); + System.out.println("[Main.java, Info]: setted the trx-frequency updated by ucxlog to: " + + chatcontroller.getChatPreferences().isTrxSynch_ucxLogUDPListenerEnabled()); + } + } + }); + + // Thats the default behaviour of the myqrg textfield + if (this.chatcontroller.getChatPreferences().isTrxSynch_ucxLogUDPListenerEnabled()) { + txt_ownqrg.setTooltip(new Tooltip("Your cq qrg will be updated by the log program (watch prefs!)")); + txt_ownqrg.textProperty().bind(this.chatcontroller.getChatPreferences().getMYQRG());// TODO: Bind darf nur + // gemacht werden, wenn + // ucxlog-Frequenznachrichten + // ausgewerttet werden! +// System.out.println("[Main.java, Info]: MYQRG will be changed only by UCXListener"); + } else { + txt_ownqrg.setTooltip(new Tooltip("enter your cq qrg here")); +// System.out.println("[Main.java, Info]: MYQRG will be changed only by User input"); + txt_ownqrg.textProperty().addListener((observable, oldValue, newValue) -> { + + System.out.println( + "[Main.java, Info]: MYQRG Text changed from " + oldValue + " to " + newValue + " by hand"); + MYQRGButton.textProperty().set(newValue); + }); + + } + + grdPnltrx.add(generateLabeledSeparator(100, "Receive UCXLog TRX info"), 0, 0, 2, 1); + grdPnltrx.add(lblEnableTRXMsgbyUCX, 0, 1); + grdPnltrx.add(chkBxEnableTRXMsgbyUCX, 1, 1); + + VBox vbxTRXSynch = new VBox(); + vbxTRXSynch.setPadding(new Insets(10, 10, 10, 10)); + vbxTRXSynch.getChildren().addAll(grdPnltrx); + + /************************************************************************************* + * Airscout settings Tab + *************************************************************************************/ + + GridPane grdPnlAirScout = new GridPane(); + grdPnlAirScout.setPadding(new Insets(10, 10, 10, 10)); + grdPnlAirScout.setVgap(5); + grdPnlAirScout.setHgap(5); + + Label lblASEnableUDPMsgbyAS = new Label("Enable Airscout integration (needs AirScout >= V 0.9.9.5)"); + Label lblASServerName = new Label("Servername (AS options>network>UDP Server settings) [AS]:"); + Label lblASChatClientName = new Label("ChatClient name for returning server answers [KST]:"); + Label lblASUdpPort = new Label("Network-UDP-Port for Airscout-Server communication [9872]:"); + Label lblASBandName = new Label("Band-Setting for Airscout-Queries [1440000]:"); + + CheckBox chkBxEnableUDPMsgbyAS = new CheckBox(); + chkBxEnableUDPMsgbyAS.setSelected(this.chatcontroller.getChatPreferences().isAirScout_asUDPListenerEnabled()); + + chkBxEnableUDPMsgbyAS.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { + + chatcontroller.getChatPreferences() + .setAirScout_asUDPListenerEnabled(chkBxEnableUDPMsgbyAS.isSelected()); + System.out.println("[Main.java, Info]: AS communication enabled: " + newValue); + } + }); + + TextField txtFld_asServerNameString = new TextField( + chatcontroller.getChatPreferences().getAirScout_asServerNameString()); + txtFld_asServerNameString.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { +// if (GuiUtils.isNumeric(txtFldUDPPortforUCX.getText())) { + + System.out.println( + "[Main.java, Info]: AS server name resetted to: " + txtFld_asServerNameString.getText()); + chatcontroller.getChatPreferences() + .setAirScout_asServerNameString(txtFld_asServerNameString.getText()); + +// } else { +// txtFldUDPPortforUCX.setText(txtFldUDPPortforUCX.getText() + " is an invalid Port"); +// } + + } + } + }); + + TextField txtFld_asClientNameString = new TextField( + chatcontroller.getChatPreferences().getAirScout_asClientNameString()); + txtFld_asClientNameString.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { +// if (GuiUtils.isNumeric(txtFldUDPPortforUCX.getText())) { + + System.out.println( + "[Main.java, Info]: AS client name resetted to: " + txtFld_asClientNameString.getText()); + chatcontroller.getChatPreferences() + .setAirScout_asServerNameString(txtFld_asClientNameString.getText()); + +// } else { +// txtFldUDPPortforUCX.setText(txtFldUDPPortforUCX.getText() + " is an invalid Port"); +// } + + } + } + }); + + TextField txtFld_asUDPPortInt = new TextField( + chatcontroller.getChatPreferences().getAirScout_asCommunicationPort() + ""); + txtFld_asUDPPortInt.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + if (GuiUtils.isNumeric(txtFld_asUDPPortInt.getText())) { + + System.out.println("[Main.java, Info]: AS port resetted to: " + txtFld_asUDPPortInt.getText()); + chatcontroller.getChatPreferences() + .setAirScout_asCommunicationPort((Integer.parseInt(txtFld_asUDPPortInt.getText()))); + + } else { + txtFld_asUDPPortInt.setText(txtFld_asUDPPortInt.getText() + " is an invalid Port"); + } + + } + } + }); + + TextField txtFld_asQRGInt = new TextField(chatcontroller.getChatPreferences().getAirScout_asBandString() + ""); + txtFld_asQRGInt.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + if (GuiUtils.isNumeric(txtFld_asQRGInt.getText())) { + + System.out.println("[Main.java, Info]: AS qrg resetted to: " + txtFld_asQRGInt.getText()); + chatcontroller.getChatPreferences() + .setAirScout_asBandString(((Integer.parseInt(txtFld_asQRGInt.getText()))) + ""); + ; + + } else { + txtFld_asQRGInt.setText(txtFld_asQRGInt.getText() + " is an invalid bandvalue"); + } + + } + } + }); + + grdPnlAirScout.add(generateLabeledSeparator(100, "Settings for Airscout-network-communication"), 0, 0, 2, 1); + grdPnlAirScout.add(lblASEnableUDPMsgbyAS, 0, 1); + grdPnlAirScout.add(chkBxEnableUDPMsgbyAS, 1, 1); + grdPnlAirScout.add(lblASServerName, 0, 2); + grdPnlAirScout.add(txtFld_asServerNameString, 1, 2); + grdPnlAirScout.add(lblASChatClientName, 0, 3); + grdPnlAirScout.add(txtFld_asClientNameString, 1, 3); + + grdPnlAirScout.add(lblASUdpPort, 0, 4); + grdPnlAirScout.add(txtFld_asUDPPortInt, 1, 4); + grdPnlAirScout.add(lblASBandName, 0, 5); + grdPnlAirScout.add(txtFld_asQRGInt, 1, 5); + + VBox vbxAirScout = new VBox(); + vbxAirScout.setPadding(new Insets(10, 10, 10, 10)); + vbxAirScout.getChildren().addAll(grdPnlAirScout); + + /************************************************************************************* + * Notification settings Tab + *************************************************************************************/ + + GridPane grdPnlNotify = new GridPane(); + grdPnlNotify.setPadding(new Insets(10, 10, 10, 10)); + grdPnlNotify.setVgap(5); + grdPnlNotify.setHgap(5); + + Label lblNitificationInfo = new Label( + "Switch bands, prefix worked by others alert, direction notifications, notification pattern matchers"); +// CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + grdPnlNotify.add(generateLabeledSeparator(100, "Notification settings"), 0, 0, 2, 1); + grdPnlNotify.add(lblNitificationInfo, 0, 1); +// grdPnltrx.add(chkBxEnableTRXMsgbyUCX, 1, 1); + + VBox vbxNotify = new VBox(); + vbxNotify.setPadding(new Insets(10, 10, 10, 10)); + vbxNotify.getChildren().addAll(grdPnlNotify); + + /************************************************************************************* + * shorts & snippets tab + *************************************************************************************/ + + GridPane grdPnlShorts = new GridPane(); + grdPnlShorts.setPadding(new Insets(10, 10, 10, 10)); + grdPnlShorts.setVgap(5); + grdPnlShorts.setHgap(5); + +// Label lblEnableTRXMsgbyUCX = new Label("Receive UCXLog network based UDP trx messages"); +// CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + grdPnlShorts.add(generateLabeledSeparator(100, "Set the shortcut-Buttons (above Sendtext-field)"), 0, 0, 2, 1); + + TableView tblVw_shortcuts = new TableView(); + tblVw_shortcuts = initShortcutTable(); + tblVw_shortcuts.setItems(this.chatcontroller.getChatPreferences().getLst_txtShortCutBtnList()); + + Button btn_Short_addLine = new Button("Add new shorcut-button"); + btn_Short_addLine.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + String newTextSnippet = "CHANGE THIS TEXT VIA DOUBLECLICK or remove by deleting all text. Then hit enter key"; + chatcontroller.getChatPreferences().getLst_txtShortCutBtnList().add(0, newTextSnippet); + } + }); + + Button btn_Short_changePosPlus = new Button("move marked down"); + btn_Short_changePosPlus.setDisable(true); + Button btn_Short_changePosMinus = new Button("move marked up"); + btn_Short_changePosMinus.setDisable(true); + + HBox hbxTxtShortBtnBox = new HBox(); + + grdPnlShorts.add(hbxTxtShortBtnBox, 0, 2, 2, 1); + hbxTxtShortBtnBox.getChildren().addAll(btn_Short_addLine, btn_Short_changePosPlus, btn_Short_changePosMinus); + + grdPnlShorts.add(tblVw_shortcuts, 0, 1, 2, 1); + + TableView tblVw_textsnippets = new TableView(); + tblVw_textsnippets = initTextSnippetsTable(); + tblVw_textsnippets.setItems(this.chatcontroller.getChatPreferences().getLst_txtSnipList()); + + grdPnlShorts.add(tblVw_textsnippets, 0, 4, 2, 1); + + Button btn_Snip_addLine = new Button("Add new snippet"); + btn_Snip_addLine.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + String newTextSnippet = "CHANGE THIS TEXT VIA DOUBLECLICK or remove by deleting all text. Then hit enter key"; + chatcontroller.getChatPreferences().getLst_txtSnipList().add(0, newTextSnippet); + } + }); + + Button btn_Snbip_changePosPlus = new Button("move marked down"); + btn_Snbip_changePosPlus.setDisable(true); + Button btn_Snip_changePosMinus = new Button("move marked up"); + btn_Snip_changePosMinus.setDisable(true); + + HBox hbxTxtSnipBtnBox = new HBox(); + + grdPnlShorts.add(hbxTxtSnipBtnBox, 0, 5, 2, 1); + hbxTxtSnipBtnBox.getChildren().addAll(btn_Snip_addLine, btn_Snbip_changePosPlus, btn_Snip_changePosMinus); + +// grdPnlShorts.add(lblEnableTRXMsgbyUCX, 0, 1); +// grdPnlShorts.add(chkBxEnableTRXMsgbyUCX, 1, 1); + grdPnlShorts.add(generateLabeledSeparator(100, "Set the Text-snippets (userlist right-click textsnippets)"), 0, + 3, 2, 1); + + VBox vbxShorts = new VBox(); + vbxShorts.setPadding(new Insets(10, 10, 10, 10)); + vbxShorts.getChildren().addAll(grdPnlShorts); + + /************************************************************************************* + * Beacons / CQ messages + *************************************************************************************/ + + GridPane grdPnlBeacon = new GridPane(); + grdPnlBeacon.setPadding(new Insets(10, 10, 10, 10)); + grdPnlBeacon.setVgap(5); + grdPnlBeacon.setHgap(5); + +// Label lblEnableTRXMsgbyUCX = new Label("Receive UCXLog network based UDP trx messages"); +// CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + grdPnlBeacon.add(generateLabeledSeparator(100, "Set the Beacon (autointervalled CQ messages to public chat)"), + 0, 0, 2, 1); + grdPnlBeacon.add(new Label("Enable CQ-like beacons:"), 0, 1); + CheckBox chkBxBeaconsEnabled = new CheckBox(); + chkBxBeaconsEnabled.setSelected(this.chatcontroller.getChatPreferences().isBcn_beaconsEnabled()); + + chkBxBeaconsEnabled.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { + + chatcontroller.getChatPreferences().setBcn_beaconsEnabled(chkBxBeaconsEnabled.isSelected()); + System.out.println("[Main.java, Info]: Beacons turned on: " + newValue); + } + }); + + grdPnlBeacon.add(chkBxBeaconsEnabled, 1, 1); + + grdPnlBeacon.add(new Label("Beacon message [<100 Chars]:"), 0, 2); + + TextField txtFldBeaconText = new TextField(this.chatcontroller.getChatPreferences().getBcn_beaconText()); + grdPnlBeacon.add(txtFldBeaconText, 1, 2); + txtFldBeaconText.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + System.out.println("[Main.java, Info]: Set the beacon text to: " + + chatcontroller.getChatPreferences().getBcn_beaconText()); +// chatcontroller.getChatPreferences().setMYQRG(txt_ownqrg.getText()); + + if (txtFldBeaconText.getText().length() <= 120) { + chatcontroller.getChatPreferences().setBcn_beaconText(txtFldBeaconText.getText()); + } else { + txtFldBeaconText.setText( + "That was too long, settig " + chatcontroller.getChatPreferences().getBcn_beaconText()); + } +// MYQRGButton.setText(txt_ownqrg.getText()); + } + } + }); + + grdPnlBeacon.add(new Label("Beacon-interval [minutes, >=5]:"), 0, 3); + TextField txtFldBeaconInterval = new TextField(); + txtFldBeaconInterval.setText(this.chatcontroller.getChatPreferences().getBcn_beaconIntervalInMinutes() + ""); + + txtFldBeaconInterval.focusedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue arg0, Boolean oldPropertyValue, + Boolean newPropertyValue) { + if (newPropertyValue) { +// System.out.println("Textfield on focus"); + // Do nothing until field loses focus, user will enter his frequency + } else { + if (GuiUtils.isNumeric(txtFldBeaconInterval.getText())) { + +// chatcontroller.getChatPreferences().setMYQRG(txt_ownqrg.getText()); + chatcontroller.getChatPreferences() + .setBcn_beaconIntervalInMinutes((Integer.parseInt(txtFldBeaconInterval.getText()))); + System.out.println("[Main.java, Info]: resetted the beacon-interval to: " + + txtFldBeaconInterval.getText()); + + } else { + txtFldBeaconInterval.setText(txtFldBeaconInterval.getText() + " is an invalid time value"); + } + + } + } + }); + + grdPnlBeacon.add(txtFldBeaconInterval, 1, 3); + + VBox vbxBeacon = new VBox(); + vbxBeacon.setPadding(new Insets(10, 10, 10, 10)); + vbxBeacon.getChildren().addAll(grdPnlBeacon); + + /************************************************************************************* + * Unworked beacon PM + *************************************************************************************/ + + GridPane grdPnlUnwkdStnBeacon = new GridPane(); + grdPnlUnwkdStnBeacon.setPadding(new Insets(10, 10, 10, 10)); + grdPnlUnwkdStnBeacon.setVgap(5); + grdPnlUnwkdStnBeacon.setHgap(5); + +// Label lblEnableTRXMsgbyUCX = new Label("Receive UCXLog network based UDP trx messages"); +// CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + grdPnlUnwkdStnBeacon.add(generateLabeledSeparator(100, + "Set the unworked penetrator Beacons (intervalled PM to unworked stations)"), 0, 0, 2, 1); +// grdPnlShorts.add(lblEnableTRXMsgbyUCX, 0, 1); +// grdPnlShorts.add(chkBxEnableTRXMsgbyUCX, 1, 1); + + VBox vbxUnwkdStnBeacon = new VBox(); + vbxUnwkdStnBeacon.setPadding(new Insets(10, 10, 10, 10)); + vbxUnwkdStnBeacon.getChildren().addAll(grdPnlUnwkdStnBeacon); + + /************************************************************************************* + * Internal database section / worked stations + *************************************************************************************/ + + GridPane grdPnlInternalDBPane = new GridPane(); + grdPnlInternalDBPane.setPadding(new Insets(10, 10, 10, 10)); + grdPnlInternalDBPane.setVgap(5); + grdPnlInternalDBPane.setHgap(5); + +// Label lblEnableTRXMsgbyUCX = new Label("Receive UCXLog network based UDP trx messages"); +// CheckBox chkBxEnableTRXMsgbyUCX = new CheckBox(); + + grdPnlInternalDBPane.add( + generateLabeledSeparator(100, + "Change the settings of the internal database (worked stations, reset before a new contest!)"), + 0, 0, 2, 1); +// grdPnlShorts.add(lblEnableTRXMsgbyUCX, 0, 1); +// grdPnlShorts.add(chkBxEnableTRXMsgbyUCX, 1, 1); + + VBox vbxInternalDB = new VBox(); + vbxInternalDB.setPadding(new Insets(10, 10, 10, 10)); + vbxInternalDB.getChildren().addAll(grdPnlInternalDBPane); + + TableView tblVw_worked = new TableView(); + tblVw_worked = initWkdStnTable(); +// tblVw_worked.setItems(); TODO + + Button btn_wkdDB_reset = new Button("Reset worked-data"); + btn_wkdDB_reset.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + // TODO: get the way to the appcontroller, there should be a reset method which + // drives the db and resets the 2 worked lists, also. + + int affectedLines; + affectedLines = chatcontroller.getDbHandler().resetWorkedDataInDB(); + chatcontroller.resetWorkedInfoInGuiLists(); + + + if (affectedLines >= 0) { + + Alert a = new Alert(AlertType.INFORMATION); + + a.setTitle("Worked data"); + a.setHeaderText("All worked data had been resetted." + affectedLines + + " worked callsign entries resetted."); +// a.setContentText(chatcontroller.getChatPreferences().getProgramVersion()); + a.show(); + + } else { + Alert a = new Alert(AlertType.INFORMATION); + + a.setTitle("Worked data"); + a.setHeaderText("Something went wrong, DB have to be rebuilt or other error!"); +// a.setContentText(chatcontroller.getChatPreferences().getProgramVersion()); + a.show(); + } + + + +// System.out.println("DB reset via DBHandler needs to be implemented"); + } + }); + + HBox hbxwkdShortBtnBox = new HBox(); + + grdPnlInternalDBPane.add(hbxwkdShortBtnBox, 0, 2, 2, 1); + hbxwkdShortBtnBox.getChildren().addAll(btn_wkdDB_reset); + + grdPnlInternalDBPane.add(tblVw_worked, 0, 1, 2, 1); + + /************************************************************************************* + * Internal database section / End + *************************************************************************************/ + + /** + * Building the options tabpanel + */ + + Tab tbStationSettings = new Tab("Station", vbxStation); + Tab tbLogSynchSet = new Tab("Log synch", vbxLog); + Tab tbTRXSynchSet = new Tab("TRX synch", vbxTRXSynch); + Tab tbAirScoutSettings = new Tab("Airscout", vbxAirScout); + Tab tbNotify = new Tab("Notification", vbxNotify); + Tab tbShorts = new Tab("Shortcuts", vbxShorts); +// Tab tbMacro = new Tab("Macros" , new Label("Set the right clickable Macros")); + Tab tbBeacon = new Tab("Beacon", vbxBeacon); + Tab tbUnwkd = new Tab("Unworkedstn requester", vbxUnwkdStnBeacon); + Tab tbInternalDB = new Tab("Workedstn database", vbxInternalDB); + + tabPaneOptions.getTabs().addAll(tbStationSettings, tbLogSynchSet, tbTRXSynchSet, tbAirScoutSettings, tbNotify, + tbShorts, tbBeacon, tbUnwkd, tbInternalDB); + + optionsPanel.setLeft(tabPaneOptions); + + HBox vbxButtons = new HBox(); + vbxButtons.setPadding(new Insets(20, 20, 20, 20)); + + Button btnOptionsPnlApply = new Button("Apply/Close prefs"); + btnOptionsPnlApply.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + settingsStage.hide(); + } + }); + + Button btnOptionspnlDisconnect = new Button("Disconnect & close Chat"); + btnOptionspnlDisconnect.setDisable(false); + + btnOptionspnlDisconnect.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + closeWindowEvent(null); + + } + }); + + Button btnOptionspnlDisconnectOnly = new Button("Disconnect"); + btnOptionspnlDisconnectOnly.setDisable(true); + + btnOptionspnlDisconnect.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + closeWindowEvent(null); + + } + }); + + btnOptionspnlConnect = new Button("Connect to " + chatcontroller.getChatPreferences().getLoginChatCategory() + .getChatCategoryName(choiceBxChatChategory.getSelectionModel().getSelectedItem().getCategoryNumber())); + btnOptionspnlConnect.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + chatcontroller.getChatPreferences().setLoginCallSign(txtFldCallSign.getText()); + chatcontroller.getChatPreferences().setLoginPassword(txtFldPassword.getText()); + chatcontroller.getChatPreferences().setLoginLocator(txtFldLocator.getText()); + chatcontroller.getChatPreferences().setLoginName(txtFldName.getText()); + chatcontroller.getChatPreferences() + .setLoginChatCategory(choiceBxChatChategory.getSelectionModel().getSelectedItem()); + + // Todo: here is where all settings has to be written to the preferences + // instance +// ownChatMemberObject.setCallSign(txtFldCallSign.getText()); +// ownChatMemberObject.setPassword(txtFldPassword.getText()); +// ownChatMemberObject.setQra(txtFldLocator.getText()); +// ownChatMemberObject.setName(txtFldName.getText()); +// ownChatMemberObject.setChatCategory(choiceBxChatChategory.getSelectionModel().getSelectedItem()); +// chatcontroller.getChatPreferences().setLoginChatCategory(chatCategoryChoice); + + System.out.println("[Info] Main.java: connect clicked, using " + + chatcontroller.getChatPreferences().getLoginCallSign() + " / " + + chatcontroller.getChatPreferences().getLoginPassword() + " / " + + chatcontroller.getChatPreferences().getLoginName() + " / " + + chatcontroller.getChatPreferences().getLoginLocator() + " at category " + + choiceBxChatChategory.getSelectionModel().getSelectedItem()); + + try { + chatcontroller.execute(); // TODO:THAT IS THE MAIN POINT WHERE THE CHAT WILL BE STARTED...MUST CATCH + // Passwordfailedexc in future + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + btnOptionspnlConnect.setDisable(false); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + btnOptionspnlConnect.setDisable(false); + } + txtFldCallSign.setDisable(true); + txtFldPassword.setDisable(true); + txtFldName.setDisable(true); + txtFldLocator.setDisable(true); + choiceBxChatChategory.setDisable(true); + btnOptionspnlConnect.setDisable(true); + btnOptionspnlDisconnect.setDisable(false); + + } + }); + + Button btn_preferences_saveAsDefault = new Button("Save settings"); + btn_preferences_saveAsDefault.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + System.out.println("saved"); + + chatcontroller.getChatPreferences().writePreferencesToXmlFile(); + Alert a = new Alert(AlertType.INFORMATION); + + a.setTitle("Info"); + a.setHeaderText("Settings are stored as default to the xml config file:"); + a.setContentText(chatcontroller.getChatPreferences().getStoreAndRestorePreferencesFileName()); + a.show(); + +// ChatMessage sendMe = new ChatMessage(); +// sendMe.setMessageText(txt_chatMessageUserInput.getText()); +// sendMe.setMessageDirectedToServer(false); +// +// chatcontroller.getMessageTXBus().add(sendMe); +// +// txt_chatMessageUserInput.clear(); + + } + }); + + vbxButtons.getChildren().addAll(btnOptionspnlConnect, btn_preferences_saveAsDefault, btnOptionsPnlApply, + btnOptionspnlDisconnect, btnOptionspnlDisconnectOnly); + + AnchorPane anchorPaneOkAndSave = new AnchorPane(); + AnchorPane.setRightAnchor(vbxButtons, 10d); + AnchorPane.setBottomAnchor(vbxButtons, 10d); + + anchorPaneOkAndSave.getChildren().addAll(vbxButtons); + + optionsPanel.setBottom(anchorPaneOkAndSave); +// optionsPanel.setAlignment(vbxButtons, Pos.CENTER);; + +// VBox vBox = new VBox(tabPaneOptions); + settingsStage.setScene(new Scene(optionsPanel, 720, 768)); + +// settingsStage.getScene().getWindow().addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, this::closeWindowEvent); + + settingsStage.show(); + + } + + /** + * + * @param width, left and right of the label + * @param labelofSeperator Info text + * @return + */ + public HBox generateLabeledSeparator(int width, String labelofSeperator) { + + HBox labeledSeparator = new HBox(); + Label lblInfo = new Label(labelofSeperator); + Separator leftSeparator = new Separator(); + leftSeparator.setPrefWidth(width); + Separator rightSeparator = new Separator(); + rightSeparator.setPrefWidth(width); + labeledSeparator.getChildren().add(leftSeparator); + labeledSeparator.getChildren().add(lblInfo); + labeledSeparator.getChildren().add(rightSeparator); + labeledSeparator.setAlignment(Pos.CENTER); + + return labeledSeparator; + } + + /** + * Handles the close action of the Chatwindow + * + * @param event + */ + private void closeWindowEvent(WindowEvent event) { + System.out.println("Window close request ..."); + +// if(storageModel.dataSetChanged()) { // if the dataset has changed, alert the user with a popup + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.getButtonTypes().remove(ButtonType.OK); + alert.getButtonTypes().add(ButtonType.CANCEL); + alert.getButtonTypes().add(ButtonType.YES); + alert.setTitle("Quit application"); + alert.setContentText(String.format("Do you want to disconnect from the Chat?")); +// alert.initOwner(primaryStage.getOwner()); + Optional res = alert.showAndWait(); + + if (res.isPresent()) { + if (res.get().equals(ButtonType.CANCEL)) { +// event.consume(); + } else { + System.out.println("closewindowevent: Platform.exit"); + Platform.exit(); + } + } +// } + } + + public static void main(String[] args) { + launch(args); + } + +} diff --git a/src/main/java/kst4contest/view/Main.java b/src/main/java/kst4contest/view/Main.java new file mode 100644 index 0000000..dcf4ea2 --- /dev/null +++ b/src/main/java/kst4contest/view/Main.java @@ -0,0 +1,15 @@ +package kst4contest.view; + +/** + * Main class with simple main method. + * Workaround to avoid Error that JavaFX is missing. + */ +public class Main { + /** + * Main method that simply calls the main method inside our application class. + * @param args Commandline Arguments. + */ + public static void main(String[] args) { + Kst4ContestApplication.main(args); + } +} diff --git a/src/main/resources/praktiKST.db b/src/main/resources/praktiKST.db new file mode 100644 index 0000000..b046c79 Binary files /dev/null and b/src/main/resources/praktiKST.db differ diff --git a/src/main/resources/praktiKSTpreferences.xml b/src/main/resources/praktiKSTpreferences.xml new file mode 100644 index 0000000..8604755 --- /dev/null +++ b/src/main/resources/praktiKSTpreferences.xml @@ -0,0 +1,99 @@ + + + + DO5SA + kst4contest.test + Paule + JO51DI + 2 + + + SimpleLogFile.txt + udpReaderBackup.txt + true + 12060 + true + + + true + 144.010.00 + + + true + KST + KST + 9872 + 1440000 + + + Hi OM, + pse + turn + ant + my + dir + sked + ssb + cw + try + agn + nw + qrg + beaming + calling + lsn to + qsb + rpt + nr + ur + I + hear + you + weak + nil, sry + maybe + later + tmw + rrr + tnx + qso + 73 + ? + ! + , + /SETNAME MYQRG + MYQRG + + + Hi OM, try sked 2m? Ur QRG? + Hi OM, try sked 70cms? Ur QRG? + Hi OM, try sked 23cms? Ur QRG? + I am calling cq to ur dir, pse lsn to MYLOCATOR at MYQRG + pse ur qrg? + rrr, I move to your qrg nw, pse ant dir MYLOCATOR + Hrd you but many qrm here, pse agn + I turn my ant to you now + Sry, strong qrm by local station, may try MYQRG + Sry, in qso nw, pse qrx, I will meep you + Ur ant my dir MYLOCATOR nw? + nil? + No cw op here, pse can we use ssb? + No chance in ssb, can we use cw? + Nil till now, are you calling? + Nil here, tnx try, maybe later! + Nil, I will look for an ap and meep you then + There will be an AP in + Tnx fb qso, all ok, 73 es gl! + + + _.~'"´"'~.__.~'´ CQ CQ CQ de MYCALL, pse call us at MYQRG `'~.__.~'"`"'~._ + 5 + false + + + Hi OM, pse Sked at MYQRG or your QRG + 20 + false + OE + + diff --git a/src/test/java/kst4contest/test/TestChatPreferences.java b/src/test/java/kst4contest/test/TestChatPreferences.java new file mode 100644 index 0000000..fe0ae34 --- /dev/null +++ b/src/test/java/kst4contest/test/TestChatPreferences.java @@ -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 + + } + +} diff --git a/src/test/java/kst4contest/test/TestReadUDPASListenerThread.java b/src/test/java/kst4contest/test/TestReadUDPASListenerThread.java new file mode 100644 index 0000000..494d0df --- /dev/null +++ b/src/test/java/kst4contest/test/TestReadUDPASListenerThread.java @@ -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); + } + +} diff --git a/src/test/java/kst4contest/test/TestReadUDPUCXListenerThread.java b/src/test/java/kst4contest/test/TestReadUDPUCXListenerThread.java new file mode 100644 index 0000000..e9a1cf6 --- /dev/null +++ b/src/test/java/kst4contest/test/TestReadUDPUCXListenerThread.java @@ -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 = "\r\n" + + "\r\n" + + " UcxLog\r\n" + + " \r\n" + + " \r\n" + + " 2022-10-30 11:51:00\r\n" + + " DO5AMF\r\n" + + " 144\r\n" + + " 14400000\r\n" + + " 14400000\r\n" + + " \r\n" + + " USB\r\n" + + " DM1AO\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " EU\r\n" + + " 59\r\n" + + " 021 JN49FK\r\n" + + " 59\r\n" + + " 001 JO50LT\r\n" + + " \r\n" + + " \r\n" + + "
\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " 0\r\n" + + " \r\n" + + " 0\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " 1\r\n" + + " 1\r\n" + + " \r\n" + + " 0\r\n" + + " 0\r\n" + + " True\r\n" + + " \r\n" + + " 0\r\n" + + " LAPTOP-05GRNFHI\r\n" + + " 0C73B5B3B82C4836\r\n" + + " True\r\n" + + "
"; +// ucxUDPReader.processUCXUDPMessage(testThis); + + + testThis ="\r\n" + + "\r\n" + + " UcxLog\r\n" + + " 1\r\n" + + " 2101100\r\n" + + " 2101100\r\n" + + " CW\r\n" + + " False\r\n" + + ""; + +// ucxUDPReader =new ReadUDPbyUCXMessageThread(12060); +// ucxUDPReader.processUCXUDPMessage(testThis); + } + +} diff --git a/src/test/java/kst4contest/test/TestUCXLogFileToHashsetParser.java b/src/test/java/kst4contest/test/TestUCXLogFileToHashsetParser.java new file mode 100644 index 0000000..31f95a3 --- /dev/null +++ b/src/test/java/kst4contest/test/TestUCXLogFileToHashsetParser.java @@ -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(); + } + + } + +} diff --git a/src/test/java/kst4contest/test/UDPAirScoutSendMessages.java b/src/test/java/kst4contest/test/UDPAirScoutSendMessages.java new file mode 100644 index 0000000..fbf4875 --- /dev/null +++ b/src/test/java/kst4contest/test/UDPAirScoutSendMessages.java @@ -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); + } + } + } \ No newline at end of file diff --git a/src/test/java/kst4contest/test/testTimeGeneration.java b/src/test/java/kst4contest/test/testTimeGeneration.java new file mode 100644 index 0000000..cee6eb5 --- /dev/null +++ b/src/test/java/kst4contest/test/testTimeGeneration.java @@ -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")); + + } + +}