commit 09/02/2026

This commit is contained in:
2026-02-09 12:04:11 +07:00
parent 1790852242
commit eed96ca8c0
30 changed files with 2494 additions and 2388 deletions

View File

@@ -14,7 +14,7 @@ import commandServer.TCP_Android_Command_Server
import content.Category import content.Category
import content.Language import content.Language
import content.VoiceType import content.VoiceType
import database.Log import database.data.Log
import database.MariaDB import database.MariaDB
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -45,14 +45,7 @@ const val max_channel = 64
val apptick : Long = System.currentTimeMillis() val apptick : Long = System.currentTimeMillis()
// dipakai untuk ambil messagebank berdasarkan id // dipakai untuk ambil messagebank berdasarkan id
val urutan_bahasa = listOf(
Language.INDONESIA.name,
Language.LOCAL.name,
Language.ENGLISH.name,
Language.CHINESE.name,
Language.JAPANESE.name,
Language.ARABIC.name
)
val contentCache = ContentCache() val contentCache = ContentCache()

View File

@@ -17,9 +17,9 @@ import content.Category
import content.Language import content.Language
import content.ScheduleDay import content.ScheduleDay
import content.VoiceType import content.VoiceType
import database.Messagebank import database.data.Messagebank
import database.QueueTable import database.data.QueueTable
import database.Soundbank import database.data.Soundbank
import org.tinylog.Logger import org.tinylog.Logger
import java.time.DayOfWeek import java.time.DayOfWeek
@@ -163,7 +163,7 @@ class MainExtension01 {
* @param languages List of language yang diinginkan, default urutan_bahasa * @param languages List of language yang diinginkan, default urutan_bahasa
* @return List of Messagebank * @return List of Messagebank
*/ */
fun Get_MessageBank_by_id(id: Int, languages: List<String> = urutan_bahasa): ArrayList<Messagebank> { fun Get_MessageBank_by_id(id: Int, languages: List<String> = Language.LanguageOrder()): ArrayList<Messagebank> {
val mb_list = ArrayList<Messagebank>() val mb_list = ArrayList<Messagebank>()
var selected_voice = config.Get(configKeys.DEFAULT_VOICE_TYPE.key) var selected_voice = config.Get(configKeys.DEFAULT_VOICE_TYPE.key)
if (selected_voice.isEmpty()) selected_voice = VoiceType.VOICE_1.name if (selected_voice.isEmpty()) selected_voice = VoiceType.VOICE_1.name

View File

@@ -3,12 +3,11 @@ package commandServer
import audioPlayer import audioPlayer
import codes.Somecodes.Companion.ValidString import codes.Somecodes.Companion.ValidString
import codes.Somecodes.Companion.datetimeformat1 import codes.Somecodes.Companion.datetimeformat1
import content.Category
import content.Language import content.Language
import database.Messagebank import database.data.Messagebank
import database.QueuePaging import database.data.QueuePaging
import database.QueueTable import database.data.QueueTable
import database.Soundbank import database.data.Soundbank
import db import db
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -367,11 +366,7 @@ class TCP_Android_Command_Server {
.map { it.trim() } .map { it.trim() }
.filter { it.isNotBlank() } .filter { it.isNotBlank() }
.forEach { al -> .forEach { al ->
val sb = db.soundDB.List VARAPTOTAL.addAll(db.soundDB.Find_AirlineName_By_TAG(al))
.filter { it.Category.equals(Category.Airplane_Name.name, true) }
.filter { it.TAG.equals(al, true)}
.distinctBy { it.TAG }
VARAPTOTAL.addAll(sb)
} }
result.append(VARAPTOTAL.size).append("@") result.append(VARAPTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
@@ -385,11 +380,7 @@ class TCP_Android_Command_Server {
.map { it.trim() } .map { it.trim() }
.filter { it.isNotBlank() } .filter { it.isNotBlank() }
.forEach { ct -> .forEach { ct ->
val sb = db.soundDB.List VARCITYTOTAL.addAll(db.soundDB.Find_City_By_TAG(ct))
.filter { it.Category.equals(Category.City.name, true) }
.filter { it.TAG.equals(ct, true)}
.distinctBy { it.TAG }
VARCITYTOTAL.addAll(sb)
} }
result.append(VARCITYTOTAL.size).append("@") result.append(VARCITYTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
@@ -397,104 +388,56 @@ class TCP_Android_Command_Server {
// kirim VARPLACESTOTAL // kirim VARPLACESTOTAL
result.clear() result.clear()
result.append("VARPLACESTOTAL;") result.append("VARPLACESTOTAL;")
val VARPLACESTOTAL = mutableListOf<Soundbank>() val VARPLACESTOTAL = db.soundDB.Get_Places()
db.soundDB.List
.filter { it.Category.equals(Category.Places.name, true) }
.distinctBy { it.TAG }
.forEach {
VARPLACESTOTAL.add(it)
}
result.append(VARPLACESTOTAL.size).append("@") result.append(VARPLACESTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARSHALATTOTAL // kirim VARSHALATTOTAL
result.clear() result.clear()
result.append("VARSHALATTOTAL;") result.append("VARSHALATTOTAL;")
val VARSHALATTOTAL = mutableListOf<Soundbank>() val VARSHALATTOTAL = db.soundDB.Get_Shalat()
db.soundDB.List
.filter { it.Category.equals(Category.Shalat.name, true) }
.distinctBy { it.TAG }
.forEach {
VARSHALATTOTAL.add(it)
}
result.append(VARSHALATTOTAL.size).append("@") result.append(VARSHALATTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARSEQUENCETOTAL // kirim VARSEQUENCETOTAL
result.clear() result.clear()
result.append("VARSEQUENCETOTAL;") result.append("VARSEQUENCETOTAL;")
val VARSEQUENCETOTAL = mutableListOf<Soundbank>() val VARSEQUENCETOTAL = db.soundDB.Get_Sequences()
db.soundDB.List
.filter { it.Category.equals(Category.Sequence.name, true) }
.distinctBy { it.TAG }
.forEach {
VARSEQUENCETOTAL.add(it)
}
result.append(VARSEQUENCETOTAL.size).append("@") result.append(VARSEQUENCETOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARREASONTOTAL // kirim VARREASONTOTAL
result.clear() result.clear()
result.append("VARREASONTOTAL;") result.append("VARREASONTOTAL;")
val VARREASONTOTAL = mutableListOf<Soundbank>() val VARREASONTOTAL = db.soundDB.Get_Reasons()
db.soundDB.List
.filter { it.Category.equals(Category.Reason.name, true) }
.distinctBy { it.TAG }
.forEach {
VARREASONTOTAL.add(it)
}
result.append(VARREASONTOTAL.size).append("@") result.append(VARREASONTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARPROCEDURETOTAL // kirim VARPROCEDURETOTAL
val VARPROCEDURETOTAL = mutableListOf<Soundbank>()
result.clear() result.clear()
result.append("VARPROCEDURETOTAL;") result.append("VARPROCEDURETOTAL;")
db.soundDB.List val VARPROCEDURETOTAL = db.soundDB.Get_Procedures()
.filter { it.Category.equals(Category.Procedure.name, true) }
.distinctBy { it.TAG }
.forEach {
VARPROCEDURETOTAL.add(it)
}
result.append(VARPROCEDURETOTAL.size).append("@") result.append(VARPROCEDURETOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARGATETOTAL // kirim VARGATETOTAL
val VARGATETOTAL = mutableListOf<Soundbank>()
result.clear() result.clear()
result.append("VARGATETOTAL;") result.append("VARGATETOTAL;")
db.soundDB.List val VARGATETOTAL = db.soundDB.Get_Gates()
.filter { it.Category.equals(Category.Gate.name, true) }
.distinctBy { it.TAG }
.forEach {
VARGATETOTAL.add(it)
}
result.append(VARGATETOTAL.size).append("@") result.append(VARGATETOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARCOMPENSATIONTOTAL // kirim VARCOMPENSATIONTOTAL
result.clear() result.clear()
result.append("VARCOMPENSATIONTOTAL;") result.append("VARCOMPENSATIONTOTAL;")
val VARCOMPENSATIONTOTAL = mutableListOf<Soundbank>() val VARCOMPENSATIONTOTAL = db.soundDB.Get_Compensation()
db.soundDB.List
.filter { it.Category.equals(Category.Compensation.name, true) }
.distinctBy { it.TAG }
.forEach {
VARCOMPENSATIONTOTAL.add(it)
}
result.append(VARCOMPENSATIONTOTAL.size).append("@") result.append(VARCOMPENSATIONTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())
// kirim VARGREETINGTOTAL // kirim VARGREETINGTOTAL
result.clear() result.clear()
result.append("VARGREETINGTOTAL;") result.append("VARGREETINGTOTAL;")
val VARGREETINGTOTAL = mutableListOf<Soundbank>() val VARGREETINGTOTAL = db.soundDB.Get_Greeting()
db.soundDB.List
.filter { it.Category.equals(Category.Greeting.name, true) }
.distinctBy { it.TAG }
.forEach {
VARGREETINGTOTAL.add(it)
}
result.append(VARGREETINGTOTAL.size).append("@") result.append(VARGREETINGTOTAL.size).append("@")
cb.accept(result.toString()) cb.accept(result.toString())

View File

@@ -12,9 +12,30 @@ enum class Language(name: String) {
LOCAL("LOCAL"), LOCAL("LOCAL"),
JAPANESE("JAPANESE"), JAPANESE("JAPANESE"),
CHINESE("CHINESE"), CHINESE("CHINESE"),
ARABIC("ARABIC"); ARABIC("ARABIC"),
DEFAULT(INDONESIA.name); // default language
companion object{ companion object{
/**
* Default language link string
*/
fun DefaultLanguageLink() : String {
return DEFAULT.name+";"+ENGLISH.name
}
/**
* Default language order
*/
fun LanguageOrder() : List<String> {
return listOf(
INDONESIA.name,
LOCAL.name,
ENGLISH.name,
CHINESE.name,
JAPANESE.name,
ARABIC.name
)
}
fun from_GoogleTTSLanguage(lang: google.GoogleTTSLanguage) : Language { fun from_GoogleTTSLanguage(lang: google.GoogleTTSLanguage) : Language {
return when(lang) { return when(lang) {
google.GoogleTTSLanguage.Indonesia -> INDONESIA google.GoogleTTSLanguage.Indonesia -> INDONESIA

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
package database package database.data
@Suppress("unused") @Suppress("unused")
data class BroadcastZones(var index: UInt, var description: String, var SoundChannel: String, var id: String, var bp: String){ data class BroadcastZones(var index: UInt, var description: String, var SoundChannel: String, var id: String, var bp: String){

View File

@@ -1,4 +1,4 @@
package database package database.data
data class LanguageLink(var index: UInt, var TAG: String, var Language: String){ data class LanguageLink(var index: UInt, var TAG: String, var Language: String){

View File

@@ -1,4 +1,4 @@
package database package database.data
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime

View File

@@ -1,4 +1,4 @@
package database package database.data
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime

View File

@@ -1,4 +1,4 @@
package database package database.data
data class Messagebank( data class Messagebank(
var index : UInt, var index : UInt,

View File

@@ -1,4 +1,4 @@
package database package database.data
@Suppress("unused") @Suppress("unused")
data class QueueFids(var index: UInt, var ALCODE: String, var FLNUM: String, var ORIGIN: String, var ETAD: String, var FREMARK: String){ data class QueueFids(var index: UInt, var ALCODE: String, var FLNUM: String, var ORIGIN: String, var ETAD: String, var FREMARK: String){

View File

@@ -1,4 +1,8 @@
package database package database.data
import codes.Somecodes
import java.time.Duration
import java.time.LocalDateTime
data class QueuePaging(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var BroadcastZones: String){ data class QueuePaging(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var BroadcastZones: String){
fun isNotEmpty(): Boolean { fun isNotEmpty(): Boolean {
@@ -18,8 +22,8 @@ data class QueuePaging(var index: UInt, var Date_Time: String, var Source: Strin
*/ */
fun isExpired(qt: QueuePaging) : Boolean{ fun isExpired(qt: QueuePaging) : Boolean{
try{ try{
val t1 = java.time.LocalDateTime.parse(qt.Date_Time, codes.Somecodes.datetimeformat1) val t1 = LocalDateTime.parse(qt.Date_Time, Somecodes.datetimeformat1)
val delta = java.time.Duration.between(t1, java.time.LocalDateTime.now()) val delta = Duration.between(t1, LocalDateTime.now())
return delta.seconds > 5 return delta.seconds > 5
} catch (_: Exception){ } catch (_: Exception){
return false return false

View File

@@ -1,6 +1,7 @@
package database package database.data
import codes.Somecodes.Companion.datetimeformat1 import codes.Somecodes.Companion.datetimeformat1
import java.time.Duration
import java.time.LocalDateTime import java.time.LocalDateTime
data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){ data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){
@@ -25,7 +26,7 @@ data class QueueTable(var index: UInt, var Date_Time: String, var Source: String
fun isExpired(qt: QueueTable) : Boolean{ fun isExpired(qt: QueueTable) : Boolean{
try{ try{
val t1 = LocalDateTime.parse(qt.Date_Time, datetimeformat1) val t1 = LocalDateTime.parse(qt.Date_Time, datetimeformat1)
val delta = java.time.Duration.between(t1, LocalDateTime.now()) val delta = Duration.between(t1, LocalDateTime.now())
// expired if more than 5 seconds // expired if more than 5 seconds
return delta.seconds > 5 return delta.seconds > 5
} catch (_: Exception){ } catch (_: Exception){

View File

@@ -1,4 +1,4 @@
package database package database.data
@Suppress("unused") @Suppress("unused")
data class ScheduleBank( data class ScheduleBank(

View File

@@ -1,4 +1,4 @@
package database package database.data
data class SoundChannel(val index: UInt, val channel: String, val ip: String) { data class SoundChannel(val index: UInt, val channel: String, val ip: String) {

View File

@@ -1,5 +1,4 @@
package database package database.data
data class Soundbank( data class Soundbank(
var index: UInt, var index: UInt,

View File

@@ -1,4 +1,4 @@
package database package database.data
@Suppress("unused") @Suppress("unused")
data class UserDB(var index: UInt, var username: String, var password: String, var location: String, var airline_tags: String, var city_tags: String, var messagebank_ann_id: String, var broadcastzones: String){ data class UserDB(var index: UInt, var username: String, var password: String, var location: String, var airline_tags: String, var city_tags: String, var messagebank_ann_id: String, var broadcastzones: String){
@@ -26,6 +26,3 @@ data class UserDB(var index: UInt, var username: String, var password: String, v
} }
} }

View File

@@ -0,0 +1,203 @@
package database.table
import database.data.BroadcastZones
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_BroadcastZones(connection: Connection) : dbFunctions<BroadcastZones>("broadcastzones", connection, listOf("index", "description", "SoundChannel", "id", "bp")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"description VARCHAR(512) NOT NULL," + // Description of the broadcast zone
"SoundChannel VARCHAR(45) NOT NULL," + // Sound channel of the broadcast zone
"id VARCHAR(45) NOT NULL," + // Box of the broadcast zone
"bp VARCHAR(45) NOT NULL" + // Relay of the broadcast zone
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val zone = BroadcastZones(
resultSet.getLong("index").toUInt(),
resultSet.getString("description"),
resultSet.getString("SoundChannel"),
resultSet.getString("id"),
resultSet.getString("bp")
)
List.add(zone)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName} : ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}" )
}
}
override fun Add(data: BroadcastZones): Boolean {
try {
val statement =
connection.prepareStatement("INSERT INTO ${super.dbName} (description, SoundChannel, id, bp) VALUES (?, ?, ?, ?)")
statement?.setString(1, data.description)
statement?.setString(2, data.SoundChannel)
statement?.setString(3, data.id)
statement?.setString(4, data.bp)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Broadcast zone added: ${data.description}" as Any)
return true
} else {
Logger.warn("No broadcast zone entry added for: ${data.description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding broadcast zone entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<BroadcastZones>): Boolean {
try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (description, SoundChannel, id, bp) VALUES (?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (bz in data) {
statement.setString(1, bz.description)
statement.setString(2, bz.SoundChannel)
statement.setString(3, bz.id)
statement.setString(4, bz.bp)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk ${super.dbName} insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding ${super.dbName} entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: BroadcastZones): Boolean {
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET description = ?, SoundChannel = ?, id = ?, bp = ? WHERE `index` = ?")
statement?.setString(1, data.description)
statement?.setString(2, data.SoundChannel)
statement?.setString(3, data.id)
statement?.setString(4, data.bp)
statement?.setLong(5, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Broadcast zone updated at index $index: ${data.description}" as Any)
return true
} else {
Logger.warn("No broadcast zone entry updated at index $index for: ${data.description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating broadcast zone entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (description, SoundChannel, id, bp) SELECT description, SoundChannel, id, bp FROM ${super.dbName} ORDER BY description ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (description, SoundChannel, id, bp) SELECT description, SoundChannel, id, bp FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by description" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by description: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
val sheet = workbook.getSheet("BroadcastZones")
?: throw Exception("No sheet named 'BroadcastZones' found")
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers = arrayOf("Index", "description", "SoundChannel", "id", "bp")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing broadcast_zones
Clear()
// read each row and insert into database
val _broadcastZonesList = ArrayList<BroadcastZones>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val description = row.getCell(1)?.stringCellValue ?: continue
val soundChannel = row.getCell(2)?.stringCellValue ?: continue
val id = row.getCell(3)?.stringCellValue ?: continue
val bp = row.getCell(4)?.stringCellValue ?: continue
val broadcastZone = BroadcastZones(0u, description, soundChannel, id, bp)
_broadcastZonesList.add(broadcastZone)
}
return AddAll(_broadcastZonesList)
} catch (e: Exception) {
Logger.error { "Error importing BroadcastZones, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("BroadcastZones")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "description", "SoundChannel", "id", "bp")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("description"))
row.createCell(2).setCellValue(resultSet.getString("SoundChannel"))
row.createCell(3).setCellValue(resultSet.getString("id"))
row.createCell(4).setCellValue(resultSet.getString("bp"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting BroadcastZones, Msg: ${e.message}" }
}
return null
}
/**
* Get all distinct broadcast zone descriptions from broadcastDB
* @return a list of distinct broadcast zone descriptions sorted alphabetically
*/
fun Get_BroadcastZone_List(): List<String> {
return List
.distinctBy { it.description }
.map { it.description }
.sorted()
}
}

View File

@@ -0,0 +1,180 @@
package database.table
import database.data.LanguageLink
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_LanguageLink(connection: Connection) : dbFunctions<LanguageLink>("languagelinking", connection, listOf("index", "TAG", "Language")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"TAG VARCHAR(45) NOT NULL," + // Language tag (e.g., EN, FR)
"Language VARCHAR(128) NOT NULL" + // Full language name (e.g., English, French)
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val languageLink = LanguageLink(
resultSet.getLong("index").toUInt(),
resultSet.getString("TAG"),
resultSet.getString("Language")
)
List.add(languageLink)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName} : ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}" )
}
}
override fun Add(data: LanguageLink): Boolean {
try {
val statement = connection.prepareStatement("INSERT INTO ${super.dbName} (TAG, Language) VALUES (?, ?)")
statement.setString(1, data.TAG)
statement.setString(2, data.Language)
val rowsAffected = statement.executeUpdate()
if (rowsAffected > 0) {
Logger.info("Language link added: ${data.TAG} -> ${data.Language}" as Any)
return true
} else {
Logger.warn("No language link entry added for: ${data.TAG} -> ${data.Language}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding language link entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<LanguageLink>): Boolean {
try {
connection.autoCommit = false
val sql = "INSERT INTO ${super.dbName} (TAG, Language) VALUES (?, ?)"
val statement = connection.prepareStatement(sql)
//for (ll in List) {
for (ll in data) {
statement.setString(1, ll.TAG)
statement.setString(2, ll.Language)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk languagelinking insert successful: ${List.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding languagelinking entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: LanguageLink): Boolean {
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET TAG = ?, Language = ? WHERE `index` = ?")
statement?.setString(1, data.TAG)
statement?.setString(2, data.Language)
statement?.setLong(3, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Language link updated at index $index: ${data.TAG} -> ${data.Language}" as Any)
return true
} else {
Logger.warn("No language link entry updated at index $index for: ${data.TAG} -> ${data.Language}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating language link entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (TAG, Language) SELECT TAG, Language FROM ${super.dbName} ORDER BY TAG")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (TAG, Language) SELECT TAG, Language FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by TAG" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by TAG: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
val sheet =
workbook.getSheet("LanguageLink") ?: throw Exception("No sheet named 'LanguageLink' found")
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers = arrayOf("Index", "TAG", "Language")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing languagelink
Clear()
// read each row and insert into database
val _languageLinkList = ArrayList<LanguageLink>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val tag = row.getCell(1)?.stringCellValue ?: continue
val language = row.getCell(2)?.stringCellValue ?: continue
val languageLink = LanguageLink(0u, tag, language)
_languageLinkList.add(languageLink)
}
return AddAll(_languageLinkList)
} catch (e: Exception) {
Logger.error { "Error importing LanguageLink, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("LanguageLink")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "TAG", "Language")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("TAG"))
row.createCell(2).setCellValue(resultSet.getString("Language"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting languagelinking, Msg: ${e.message}" }
}
return null
}
}

View File

@@ -1,8 +1,11 @@
package database package database.table
import database.data.LogSemiauto
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger import org.tinylog.Logger
import java.sql.Connection import java.sql.Connection
import java.sql.Date
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.function.Consumer import java.util.function.Consumer
@@ -92,18 +95,18 @@ class Table_LogSemiAuto(connection: Connection) : dbFunctions<LogSemiauto>("logs
fun GetLogSemiAutoForHtml(date: String, filter: String?, cbOK: Consumer<ArrayList<LogSemiauto>>?, cbFail: Consumer<String>?){ fun GetLogSemiAutoForHtml(date: String, filter: String?, cbOK: Consumer<ArrayList<LogSemiauto>>?, cbFail: Consumer<String>?){
try{ try{
val valid_date : java.sql.Date? = when{ val valid_date : Date? = when{
dateformat1.matches(date) -> { dateformat1.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd/MM/yyyy"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd/MM/yyyy")))
} }
dateformat2.matches(date) -> { dateformat2.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd-MM-yyyy"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd-MM-yyyy")))
} }
dateformat3.matches(date) -> { dateformat3.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy/MM/dd"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy/MM/dd")))
} }
dateformat4.matches(date) -> { dateformat4.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))
} }
else -> null else -> null
} }

View File

@@ -1,8 +1,11 @@
package database package database.table
import database.data.Log
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger import org.tinylog.Logger
import java.sql.Connection import java.sql.Connection
import java.sql.Date
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.function.Consumer import java.util.function.Consumer
@@ -44,18 +47,18 @@ class Table_Logs(connection: Connection) : dbFunctions<Log> ("logs", connection,
fun GetLogForHtml(date: String, filter: String?, cbOK: Consumer<ArrayList<Log>>?, cbFail: Consumer<String>?){ fun GetLogForHtml(date: String, filter: String?, cbOK: Consumer<ArrayList<Log>>?, cbFail: Consumer<String>?){
try{ try{
val valid_date : java.sql.Date? = when{ val valid_date : Date? = when{
dateformat1.matches(date) -> { dateformat1.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd/MM/yyyy"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd/MM/yyyy")))
} }
dateformat2.matches(date) -> { dateformat2.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd-MM-yyyy"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("dd-MM-yyyy")))
} }
dateformat3.matches(date) -> { dateformat3.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy/MM/dd"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy/MM/dd")))
} }
dateformat4.matches(date) -> { dateformat4.matches(date) -> {
java.sql.Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"))) Date.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))
} }
else -> null else -> null
} }
@@ -202,6 +205,74 @@ class Table_Logs(connection: Connection) : dbFunctions<Log> ("logs", connection,
throw Exception("Importing Logs from XLSX is not supported") throw Exception("Importing Logs from XLSX is not supported")
} }
/**
* Exports the log table to an XLSX workbook for a specific date and optional filter.
* @param logDate The date string in format "dd/MM/yyyy".
* @param logFilter The filter string for the description or machine. If empty, exports all logs for the date.
* @return An XSSFWorkbook containing the filtered log data, or null if an error occurred.
*/
fun Export_Log_XLSX(logDate: String, logFilter: String): XSSFWorkbook? {
try {
val valid_date : Date? = when{
dateformat1.matches(logDate) -> {
Date.valueOf(LocalDate.parse(logDate, DateTimeFormatter.ofPattern("dd/MM/yyyy")))
}
dateformat2.matches(logDate) -> {
Date.valueOf(LocalDate.parse(logDate, DateTimeFormatter.ofPattern("dd-MM-yyyy")))
}
dateformat3.matches(logDate) -> {
Date.valueOf(LocalDate.parse(logDate, DateTimeFormatter.ofPattern("yyyy/MM/dd")))
}
dateformat4.matches(logDate) -> {
Date.valueOf(LocalDate.parse(logDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))
}
else -> null
}
if (valid_date!=null){
// use coalescing for different datenya formats
val statement = if (logFilter.isEmpty()){
connection.prepareStatement("SELECT * FROM ${super.dbName} WHERE COALESCE(STR_TO_DATE(datenya,'%d/%m/%Y'), STR_TO_DATE(datenya,'%d-%m-%Y'), STR_TO_DATE(datenya,'%Y/%m/%d'), STR_TO_DATE(datenya,'%Y-%m-%d')) = ?")
} else {
connection.prepareStatement("SELECT * FROM ${super.dbName} WHERE COALESCE(STR_TO_DATE(datenya,'%d/%m/%Y'), STR_TO_DATE(datenya,'%d-%m-%Y'), STR_TO_DATE(datenya,'%Y/%m/%d'), STR_TO_DATE(datenya,'%Y-%m-%d')) = ? AND description LIKE ?")
}
statement?.setDate(1, valid_date)
if (logFilter.isNotEmpty()){
statement?.setString(2, "%$logFilter%")
}
val resultSet = statement?.executeQuery()
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("Log")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "datenya", "timenya", "machine", "description")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("datenya"))
row.createCell(2).setCellValue(resultSet.getString("timenya"))
row.createCell(3).setCellValue(resultSet.getString("machine"))
row.createCell(4).setCellValue(resultSet.getString("description"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} else throw Exception("Invalid date")
} catch (e: Exception) {
Logger.error { "Error exporting Log, Msg: ${e.message}" }
}
return null
}
override fun Export_XLSX(): XSSFWorkbook? { override fun Export_XLSX(): XSSFWorkbook? {
try { try {
val statement = connection.createStatement() val statement = connection.createStatement()

View File

@@ -0,0 +1,239 @@
package database.table
import database.data.Messagebank
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_Messagebank(connection: Connection) : dbFunctions<Messagebank>("messagebank", connection, listOf("index", "Description", "Language", "ANN_ID", "Voice_Type", "Message_Detail", "Message_TAGS")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"Description VARCHAR(512) NOT NULL," + // Description of the message
"Language VARCHAR(45) NOT NULL," + // Language of the message
"ANN_ID INT NOT NULL," + // ANN ID of the message
"Voice_Type VARCHAR(45) NOT NULL," + // Voice type of the message
"Message_Detail VARCHAR(1024) NOT NULL," + // Full message text
"Message_TAGS VARCHAR(1024)" + // Comma-separated tags for the message
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val messagebank = Messagebank(
resultSet.getLong("index").toUInt(),
resultSet.getString("Description"),
resultSet.getString("Language"),
resultSet.getInt("ANN_ID").toUInt(),
resultSet.getString("Voice_Type"),
resultSet.getString("Message_Detail"),
resultSet.getString("Message_TAGS")
)
List.add(messagebank)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName} : ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}")
}
}
override fun Add(data: Messagebank): Boolean {
try {
val statement =
connection.prepareStatement("INSERT INTO ${super.dbName} (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) VALUES (?, ?, ?, ?, ?, ?)")
statement?.setString(1, data.Description)
statement?.setString(2, data.Language)
statement?.setInt(3, data.ANN_ID.toInt())
statement?.setString(4, data.Voice_Type)
statement?.setString(5, data.Message_Detail)
statement?.setString(6, data.Message_TAGS)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Messagebank added: ${data.Description}" as Any)
return true
} else {
Logger.warn("No messagebank entry added for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding messagebank entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<Messagebank>): Boolean {
try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) VALUES (?, ?, ?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (mb in data) {
statement.setString(1, mb.Description)
statement.setString(2, mb.Language)
statement.setInt(3, mb.ANN_ID.toInt())
statement.setString(4, mb.Voice_Type)
statement.setString(5, mb.Message_Detail)
statement.setString(6, mb.Message_TAGS)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk messagebank insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding messagebank entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: Messagebank): Boolean {
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET Description = ?, Language = ?, ANN_ID = ?, Voice_Type = ?, Message_Detail = ?, Message_TAGS = ? WHERE `index` = ?")
statement?.setString(1, data.Description)
statement?.setString(2, data.Language)
statement?.setInt(3, data.ANN_ID.toInt())
statement?.setString(4, data.Voice_Type)
statement?.setString(5, data.Message_Detail)
statement?.setString(6, data.Message_TAGS)
statement?.setLong(7, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Messagebank updated at index $index: ${data.Description}" as Any)
return true
} else {
Logger.warn("No messagebank entry updated at index $index for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating messagebank entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) SELECT Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS FROM ${super.dbName} ORDER BY ANN_ID ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) SELECT Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by Description" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by Description: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
// check if there is sheet named "Messagebank"
val sheet =
workbook.getSheet("Messagebank") ?: throw Exception("No sheet named 'Messagebank' found")
// check if the sheet contains header named "Index", "Description", "Language", "ANN_ID", "Voice_Type", "Message_Detail", "Message_TAGS"
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers =
arrayOf(
"Index",
"Description",
"Language",
"ANN_ID",
"Voice_Type",
"Message_Detail",
"Message_TAGS"
)
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing messagebank
Clear()
// read each row and insert into database
val _messagebankList = ArrayList<Messagebank>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val description = row.getCell(1)?.stringCellValue ?: continue
val language = row.getCell(2)?.stringCellValue ?: continue
val annId = row.getCell(3)?.stringCellValue?.toUIntOrNull() ?: continue
val voiceType = row.getCell(4)?.stringCellValue ?: continue
val messageDetail = row.getCell(5)?.stringCellValue ?: continue
val messageTags = row.getCell(6)?.stringCellValue ?: continue
val messagebank =
Messagebank(0u, description, language, annId, voiceType, messageDetail, messageTags)
_messagebankList.add(messagebank)
}
return AddAll(_messagebankList)
} catch (e: Exception) {
Logger.error { "Error importing Messagebank, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("Messagebank")
val headerRow = sheet.createRow(0)
val headers =
arrayOf(
"Index",
"Description",
"Language",
"ANN_ID",
"Voice_Type",
"Message_Detail",
"Message_TAGS"
)
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("Description"))
row.createCell(2).setCellValue(resultSet.getString("Language"))
row.createCell(3).setCellValue(resultSet.getString("ANN_ID"))
row.createCell(4).setCellValue(resultSet.getString("Voice_Type"))
row.createCell(5).setCellValue(resultSet.getString("Message_Detail"))
row.createCell(6).setCellValue(resultSet.getString("Message_TAGS"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting Messagebank, Msg: ${e.message}" }
}
return null
}
/**
* Get all distinct message ID from messagebank
* @return a list of distinct ANN_ID sorted numerically
*/
fun Get_MessageID_List(): List<UInt> {
return List
.distinctBy { it.ANN_ID }
.map { it.ANN_ID }
.sorted()
}
}

View File

@@ -0,0 +1,156 @@
package database.table
import database.data.QueuePaging
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_QueuePaging(connection : Connection) : dbFunctions<QueuePaging>("queue_paging", connection, listOf("index", "Date_Time", "Source", "Type", "Message", "BroadcastZones")) {
override fun Create() {
val tabledefinition ="CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"Date_Time VARCHAR(45) NOT NULL," + // Date and time of the entry
"Source VARCHAR(45) NOT NULL," + // Source of the entry
"Type VARCHAR(45) NOT NULL," + // Type of the entry
"Message VARCHAR(1024) NOT NULL," + // Message content
"BroadcastZones VARCHAR(1024)" + // Comma-separated soundbank tags
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
val queueList = ArrayList<QueuePaging>()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val queuePaging = QueuePaging(
resultSet.getLong("index").toUInt(),
resultSet.getString("Date_Time"),
resultSet.getString("Source"),
resultSet.getString("Type"),
resultSet.getString("Message"),
resultSet.getString("BroadcastZones"),
)
queueList.add(queuePaging)
List.add(queuePaging)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName} : ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}" )
}
}
override fun Add(data: QueuePaging): Boolean {
try {
val statement = connection.prepareStatement(
"INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, BroadcastZones) VALUES (?, ?, ?, ?, ?)"
)
statement?.setString(1, data.Date_Time)
statement?.setString(2, data.Source)
statement?.setString(3, data.Type)
statement?.setString(4, data.Message)
statement?.setString(5, data.BroadcastZones)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("QueuePaging added: ${data.Message}" as Any)
return true
} else {
Logger.warn("No QueuePaging entry added for: ${data.Message}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding QueuePaging entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<QueuePaging>): Boolean {
return try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, BroadcastZones) VALUES (?, ?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (qp in data) {
statement.setString(1, qp.Date_Time)
statement.setString(2, qp.Source)
statement.setString(3, qp.Type)
statement.setString(4, qp.Message)
statement.setString(5, qp.BroadcastZones)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk QueuePaging insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
true
} catch (e: Exception) {
Logger.error("Error adding QueuePaging entries: ${e.message}" as Any)
false
}
}
override fun UpdateByIndex(index: Int, data: QueuePaging): Boolean {
throw Exception("Update not supported")
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (Date_Time, Source, Type, Message, BroadcastZones) SELECT Date_Time, Source, Type, Message, BroadcastZones FROM ${super.dbName} ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, BroadcastZones) SELECT Date_Time, Source, Type, Message, BroadcastZones FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by index" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by index: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
throw Exception("Importing QueuePaging from XLSX is not supported")
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("QueuePaging")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "Date_Time", "Source", "Type", "Message", "BroadcastZones")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("Date_Time"))
row.createCell(2).setCellValue(resultSet.getString("Source"))
row.createCell(3).setCellValue(resultSet.getString("Type"))
row.createCell(4).setCellValue(resultSet.getString("Message"))
row.createCell(5).setCellValue(resultSet.getString("BroadcastZones"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting QueuePaging, Msg: ${e.message}" }
}
return null
}
}

View File

@@ -0,0 +1,181 @@
package database.table
import database.data.QueueTable
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_QueueSoundbank(connection: Connection) : dbFunctions<QueueTable>("queue_table", connection, listOf("index", "Date_Time", "Source", "Type", "Message", "SB_TAGS", "BroadcastZones", "Repeat", "Language")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"Date_Time VARCHAR(45) NOT NULL," + // Date and time of the entry
"Source VARCHAR(45) NOT NULL," + // Source of the entry
"Type VARCHAR(45) NOT NULL," + // Type of the entry
"Message VARCHAR(1024) NOT NULL," + // Message content
"SB_TAGS VARCHAR(1024)," + // Comma-separated soundbank tags
"BroadcastZones VARCHAR(1024) NOT NULL," + // Comma-separated broadcast zones
"`Repeat` INT NOT NULL," + // Number of repeats
"Language VARCHAR(100) NOT NULL" + // Language of the message
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
val queueList = ArrayList<QueueTable>()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val queueTable = QueueTable(
resultSet.getLong("index").toUInt(),
resultSet.getString("Date_Time"),
resultSet.getString("Source"),
resultSet.getString("Type"),
resultSet.getString("Message"),
resultSet.getString("SB_TAGS"),
resultSet.getString("BroadcastZones"),
resultSet.getInt("Repeat").toUInt(),
resultSet.getString("Language")
)
queueList.add(queueTable)
List.add(queueTable)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName} : ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}" )
}
}
override fun Add(data: QueueTable): Boolean {
try {
val statement = connection.prepareStatement(
"INSERT INTO ${super.dbName} (`Date_Time`, `Source`, `Type`, `Message`, `SB_TAGS`, `BroadcastZones`, `Repeat`, `Language`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
)
statement?.setString(1, data.Date_Time)
statement?.setString(2, data.Source)
statement?.setString(3, data.Type)
statement?.setString(4, data.Message)
statement?.setString(5, data.SB_TAGS)
statement?.setString(6, data.BroadcastZones)
statement?.setInt(7, data.Repeat.toInt())
statement?.setString(8, data.Language)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("QueueTable added Source=${data.Source} Type=${data.Type} Message=${data.Message}, Languages=${data.Language} Variables=${data.SB_TAGS}, BroadcastZones=${data.BroadcastZones}" as Any)
return true
} else {
Logger.warn("No QueueTable entry added for: ${data.Message}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding QueueTable entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<QueueTable>): Boolean {
try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (`Date_Time`, `Source`, `Type`, `Message`, `SB_TAGS`, `BroadcastZones`, `Repeat`, `Language`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (qt in data) {
statement.setString(1, qt.Date_Time)
statement.setString(2, qt.Source)
statement.setString(3, qt.Type)
statement.setString(4, qt.Message)
statement.setString(5, qt.SB_TAGS)
statement.setString(6, qt.BroadcastZones)
statement.setInt(7, qt.Repeat.toInt())
statement.setString(8, qt.Language)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk QueueTable insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding QueueTable entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: QueueTable): Boolean {
throw Exception("Update not supported")
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, `Repeat`, Language) SELECT Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, `Repeat`, Language FROM ${super.dbName} ORDER BY `index` ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, `Repeat`, Language) SELECT Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, `Repeat`, Language FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by index" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by index: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
throw Exception("Import XLSX not supported for QueueTable")
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("QueueTable")
val headerRow = sheet.createRow(0)
val headers = arrayOf(
"Index",
"Date_Time",
"Source",
"Type",
"Message",
"SB_TAGS",
"BroadcastZones",
"Repeat",
"Language"
)
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("Date_Time"))
row.createCell(2).setCellValue(resultSet.getString("Source"))
row.createCell(3).setCellValue(resultSet.getString("Type"))
row.createCell(4).setCellValue(resultSet.getString("Message"))
row.createCell(5).setCellValue(resultSet.getString("SB_TAGS"))
row.createCell(6).setCellValue(resultSet.getString("BroadcastZones"))
row.createCell(7).setCellValue(resultSet.getString("Repeat"))
row.createCell(8).setCellValue(resultSet.getString("Language"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting QueueTable, Msg: ${e.message}" }
}
return null
}
}

View File

@@ -0,0 +1,287 @@
package database.table
import codes.Somecodes.Companion.ValidScheduleDay
import database.MariaDB.Companion.ValidTime
import database.data.ScheduleBank
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_Schedule(connection: Connection) : dbFunctions<ScheduleBank>("schedulebank", connection, listOf("index", "Description", "Day", "Time", "Soundpath", "Repeat", "Enable", "BroadcastZones", "Language")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"Description VARCHAR(128) NOT NULL," + // Description of the schedule
"Day VARCHAR(255) NOT NULL," + // Day in format DD/MM/YYYY
"Time VARCHAR(20) NOT NULL," + // Time in format HH:MM:SS
"Soundpath VARCHAR(512) NOT NULL," + // Path to the sound file
"`Repeat` TINYINT UNSIGNED NOT NULL," + // Repeat type (0=Once, 1=Daily, 2=Weekly, 3=Monthly, 4=Yearly)
"Enable BOOLEAN NOT NULL," + // Enable or disable the schedule
"BroadcastZones TEXT NOT NULL," + // Comma-separated list of broadcast zones
"Language VARCHAR(45) NOT NULL" + // Language code (e.g., EN, FR)
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val schedulebank = ScheduleBank(
resultSet.getLong("index").toUInt(),
resultSet.getString("Description"),
resultSet.getString("Day"),
resultSet.getString("Time"),
resultSet.getString("Soundpath"),
resultSet.getInt("Repeat").toUByte(),
resultSet.getBoolean("Enable"),
resultSet.getString("BroadcastZones"),
resultSet.getString("Language")
)
List.add(schedulebank)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching ${super.dbName}: ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName}: ${e.message}" )
}
}
override fun Add(data: ScheduleBank): Boolean {
if (!ValidScheduleDay(data.Day)) {
Logger.error("Error adding schedulebank entry: Invalid date format ${data.Day}" as Any)
return false
}
if (!ValidTime(data.Time)) {
Logger.error("Error adding schedulebank entry: Invalid time format ${data.Time}" as Any)
return false
}
try {
val statement =
connection.prepareStatement("INSERT INTO ${super.dbName} (Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")
statement?.setString(1, data.Description)
statement?.setString(2, data.Day)
statement?.setString(3, data.Time)
statement?.setString(4, data.Soundpath)
statement?.setInt(5, data.Repeat.toInt())
statement?.setBoolean(6, data.Enable)
statement?.setString(7, data.BroadcastZones)
statement?.setString(8, data.Language)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Schedulebank added: ${data.Description}" as Any)
return true
} else {
Logger.warn("No schedulebank entry added for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding schedulebank entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<ScheduleBank>): Boolean {
try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (sb in data) {
if (!ValidScheduleDay(sb.Day) || !ValidTime(sb.Time)) {
Logger.error("Invalid date or time format for schedulebank: ${sb.Description}" as Any)
continue
}
statement.setString(1, sb.Description)
statement.setString(2, sb.Day)
statement.setString(3, sb.Time)
statement.setString(4, sb.Soundpath)
statement.setInt(5, sb.Repeat.toInt())
statement.setBoolean(6, sb.Enable)
statement.setString(7, sb.BroadcastZones)
statement.setString(8, sb.Language)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk schedulebank insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding schedulebank entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: ScheduleBank): Boolean {
if (!ValidScheduleDay(data.Day)) {
Logger.error("Error updating schedulebank entry: Invalid date format ${data.Day}" as Any)
return false
}
if (!ValidTime(data.Time)) {
Logger.error("Error updating schedulebank entry: Invalid time format ${data.Time}" as Any)
return false
}
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET Description = ?, Day = ?, Time = ?, Soundpath = ?, `Repeat` = ?, Enable = ?, BroadcastZones = ?, Language = ? WHERE `index` = ?")
statement?.setString(1, data.Description)
statement?.setString(2, data.Day)
statement?.setString(3, data.Time)
statement?.setString(4, data.Soundpath)
statement?.setInt(5, data.Repeat.toInt())
statement?.setBoolean(6, data.Enable)
statement?.setString(7, data.BroadcastZones)
statement?.setString(8, data.Language)
statement?.setLong(9, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Schedulebank updated at index $index: ${data.Description}" as Any)
return true
} else {
Logger.warn("No schedulebank entry updated at index $index for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating schedulebank entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language) SELECT Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language FROM ${super.dbName} ORDER BY Day , Time ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language) SELECT Description, Day, Time, Soundpath, `Repeat`, Enable, BroadcastZones, Language FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by Day and Time" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by Day and Time: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
val sheet =
workbook.getSheet("Schedulebank") ?: throw Exception("No sheet named 'Schedulebank' found")
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers = arrayOf(
"Index",
"Description",
"Day",
"Time",
"Soundpath",
"Repeat",
"Enable",
"BroadcastZones",
"Language"
)
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing schedulebank
Clear()
// read each row and insert into database
val _schedulebankList = ArrayList<ScheduleBank>()
//Logger.info{"Sheet last row num: ${sheet.lastRowNum}"}
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
//println(row)
val description = row.getCell(1)?.stringCellValue ?: continue
//println(description.toString())
val day = row.getCell(2)?.stringCellValue ?: continue
//println(day.toString())
val time = row.getCell(3)?.stringCellValue ?: continue
//println(time.toString())
val soundpath = row.getCell(4)?.stringCellValue ?: continue
//println(soundpath.toString())
val repeat = row.getCell(5)?.stringCellValue?.toUByteOrNull() ?: continue
// println(repeat.toString())
//val enable = row.getCell(6)?.stringCellValue?.toBooleanStrictOrNull() ?: continue
val enable = row.getCell(6)?.stringCellValue?.toBoolean() ?: continue
//println(enable.toString())
val broadcastZones = row.getCell(7)?.stringCellValue ?: continue
//println(broadcastZones.toString())
val language = row.getCell(8)?.stringCellValue ?: continue
//println(language.toString())
val schedulebank =
ScheduleBank(
0u,
description,
day,
time,
soundpath,
repeat,
enable,
broadcastZones,
language
)
Logger.info{"SchedulebankList added 1"}
_schedulebankList.add(schedulebank)
}
return AddAll(_schedulebankList)
} catch (e: Exception) {
Logger.error { "Error importing Schedulebank, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("Schedulebank")
val headerRow = sheet.createRow(0)
val headers = arrayOf(
"Index",
"Description",
"Day",
"Time",
"Soundpath",
"Repeat",
"Enable",
"BroadcastZones",
"Language"
)
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("Description"))
row.createCell(2).setCellValue(resultSet.getString("Day"))
row.createCell(3).setCellValue(resultSet.getString("Time"))
row.createCell(4).setCellValue(resultSet.getString("Soundpath"))
row.createCell(5).setCellValue(resultSet.getString("Repeat"))
row.createCell(6).setCellValue(resultSet.getString("Enable"))
row.createCell(7).setCellValue(resultSet.getString("BroadcastZones"))
row.createCell(8).setCellValue(resultSet.getString("Language"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting Schedulebank, Msg: ${e.message}" }
}
return null
}
}

View File

@@ -0,0 +1,256 @@
package database.table
import database.data.SoundChannel
import database.dbFunctions
import max_channel
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_SoundChannel(connection: Connection) : dbFunctions<SoundChannel>("soundchannel", connection, listOf("index", "channel", "ip")) {
override fun Create() {
val tableDefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"channel VARCHAR(45) NOT NULL," + // Channel 01 to Channel 64
"ip VARCHAR(45) NOT NULL" + // IP address or empty string
")"
super.Create(tableDefinition)
// Check if table is empty, if so, populate with 64 channels
try {
val statement = connection.createStatement()
val countResult = statement?.executeQuery("SELECT COUNT(*) AS count FROM ${super.dbName}")
if (countResult?.next() == true) {
val count = countResult.getInt("count")
if (count < max_channel) {
Logger.info("SoundChannel table is empty, populating with default channels" as Any)
Clear()
}
}
} catch (e: Exception) {
Logger.error("Error creating SoundChannel table: ${e.message}" as Any)
}
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName} ORDER BY `index` ")
while (resultSet?.next() == true) {
val channel = SoundChannel(
resultSet.getLong("index").toUInt(),
resultSet.getString("channel"),
resultSet.getString("ip")
)
List.add(channel)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching sound channels: ${e.message}" as Any)
cbFail?.accept("Error fetching sound channels: ${e.message}" )
}
}
override fun Add(data: SoundChannel): Boolean {
try {
val statement = connection.prepareStatement("UPDATE ${super.dbName} SET ip = ? WHERE channel = ?")
statement?.setString(1, data.ip)
statement?.setString(2, data.channel)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("SoundChannel updated: ${data.channel} -> ${data.ip}" as Any)
return true
} else {
Logger.warn("No SoundChannel entry updated for: ${data.channel} -> ${data.ip}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating SoundChannel entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<SoundChannel>): Boolean {
return try {
connection.autoCommit = false
val sql = "UPDATE ${super.dbName} SET ip = ? WHERE channel = ?"
val statement = connection.prepareStatement(sql)
for (sc in data) {
statement.setString(1, sc.ip)
statement.setString(2, sc.channel)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk SoundChannel update successful: ${data.size} entries" as Any)
connection.autoCommit = true
true
} catch (e: Exception) {
Logger.error("Error updating SoundChannel entries: ${e.message}" as Any)
false
}
}
override fun UpdateByIndex(index: Int, data: SoundChannel): Boolean {
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET channel = ?, ip = ? WHERE `index` = ?")
statement?.setString(1, data.channel)
statement?.setString(2, data.ip)
statement?.setLong(3, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("SoundChannel updated at index $index: ${data.channel} -> ${data.ip}" as Any)
return true
} else {
Logger.warn("No Sound Channel entry updated at index $index for: ${data.channel} -> ${data.ip}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating SoundChannel entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (channel, ip) SELECT channel, ip FROM ${super.dbName} ORDER BY `index` ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (channel, ip) SELECT channel, ip FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by index" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by index: ${e.message}" as Any)
}
return false
}
override fun Clear(): Boolean {
try {
val statement = connection.createStatement()
// use TRUNCATE to reset auto increment index
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
Logger.info("${super.dbName} table cleared" as Any)
List.clear()
// create new rows from 1 to 64 with description "Channel 1" to "Channel 64" and empty ip
for (i in 1..max_channel) {
val channel = String.format("Channel %d", i)
val insertStatement =
connection.prepareStatement("INSERT INTO ${super.dbName} (channel, ip) VALUES (?, ?)")
insertStatement?.setString(1, channel)
insertStatement?.setString(2, "")
insertStatement?.executeUpdate()
}
return true
} catch (e: Exception) {
Logger.error("Error clearing soundchannel table: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
val sheet =
workbook.getSheet("SoundChannel") ?: throw Exception("No sheet named 'SoundChannel' found")
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers = arrayOf("Index", "channel", "ip")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing soundchannel
Clear()
// read each row and insert into database
val _soundChannelList = ArrayList<SoundChannel>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val channel = row.getCell(1)?.stringCellValue ?: continue
val ip = row.getCell(2)?.stringCellValue ?: continue
val soundChannel = SoundChannel(0u, channel, ip)
_soundChannelList.add(soundChannel)
}
// Bulk update IPs for channels
var success = true
for (sc in _soundChannelList) {
if (!Add(sc)) {
success = false
}
}
return success
} catch (e: Exception) {
Logger.error { "Error importing SoundChannel, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("SoundChannel")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "channel", "ip")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("channel"))
row.createCell(2).setCellValue(resultSet.getString("ip"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting SoundChannel, Msg: ${e.message}" }
}
return null
}
/**
* Delete entry by index, but only clear the IP field
* @param index The index of the entry to delete
* @return true if successful, false otherwise
*/
override fun DeleteByIndex(index: Int): Boolean {
try {
val statement = connection.prepareStatement("UPDATE ${super.dbName} SET ip = '' WHERE `index` = ?")
statement?.setLong(1, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("${super.dbName} IP cleared for index $index" as Any)
return true
} else {
Logger.warn("No ${super.dbName} entry cleared for index $index" as Any)
}
} catch (e: Exception) {
Logger.error("Error clearing ${super.dbName} entry for index $index: ${e.message}" as Any)
}
return false
}
/**
* Get all distinct sound channel from soundchannelDB
* @return a list of distinct sound channel sorted alphabetically
*/
fun Get_SoundChannel_List(): List<String> {
return List
.distinctBy { it.channel }
.map { it.channel }
.sorted()
}
}

View File

@@ -0,0 +1,308 @@
package database.table
import content.Category
import database.data.Soundbank
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_Soundbank(connection: Connection) : dbFunctions<Soundbank>("soundbank", connection, listOf("index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")) {
override fun Create() {
val tabledefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"Description VARCHAR(1024) NOT NULL," + // Description of the soundbank
"TAG VARCHAR(45) NOT NULL," + // TAG of the soundbank
"Category VARCHAR(45) NOT NULL," + // Category of the soundbank
"Language VARCHAR(45) NOT NULL," + // Language of the soundbank
"VoiceType VARCHAR(45) NOT NULL," + // VoiceType of the soundbank
"Path VARCHAR(1024) NOT NULL" + // Path to the sound file
")"
super.Create(tabledefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName} ORDER BY Category, Language, VoiceType, TAG")
while (resultSet?.next() == true) {
val soundbank = Soundbank(
resultSet.getLong("index").toUInt(),
resultSet.getString("Description"),
resultSet.getString("TAG"),
resultSet.getString("Category"),
resultSet.getString("Language"),
resultSet.getString("VoiceType"),
resultSet.getString("Path")
)
List.add(soundbank)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching soundbanks: ${e.message}" as Any)
cbFail?.accept("Error fetching ${super.dbName} : ${e.message}")
}
}
override fun Add(data: Soundbank): Boolean {
try {
val statement =
connection.prepareStatement("INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) VALUES (?, ?, ?, ?, ?, ?)")
statement?.setString(1, data.Description)
statement?.setString(2, data.TAG)
statement?.setString(3, data.Category)
statement?.setString(4, data.Language)
statement?.setString(5, data.VoiceType)
statement?.setString(6, data.Path)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Soundbank added: ${data.Description}" as Any)
return true
} else {
Logger.warn("No soundbank entry added for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding soundbank entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<Soundbank>): Boolean {
// use mysql bulk insert
try {
connection.autoCommit = false
val sql =
"INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) VALUES (?, ?, ?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (sb in data) {
statement.setString(1, sb.Description)
statement.setString(2, sb.TAG)
statement.setString(3, sb.Category)
statement.setString(4, sb.Language)
statement.setString(5, sb.VoiceType)
statement.setString(6, sb.Path)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk soundbank insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
return true
} catch (e: Exception) {
Logger.error("Error adding soundbank entries: ${e.message}" as Any)
}
return false
}
override fun UpdateByIndex(index: Int, data: Soundbank): Boolean {
try {
val statement =
connection.prepareStatement("UPDATE ${super.dbName} SET Description = ?, TAG = ?, Category = ?, Language = ?, VoiceType = ?, Path = ? WHERE `index` = ?")
statement?.setString(1, data.Description)
statement?.setString(2, data.TAG)
statement?.setString(3, data.Category)
statement?.setString(4, data.Language)
statement?.setString(5, data.VoiceType)
statement?.setString(6, data.Path)
statement?.setLong(7, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("Soundbank updated at index $index: ${data.Description}" as Any)
return true
} else {
Logger.warn("No soundbank entry updated at index $index for: ${data.Description}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating soundbank entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM ${super.dbName} ORDER BY Category, Language, VoiceType, TAG ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by Description" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by Description: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
// check if there is sheet named "Soundbank"
val sheet =
workbook.getSheet("Soundbank") ?: throw Exception("No sheet named 'Soundbank' found")
// check if the sheet contains header named "index", "Description", "TAG", "Category", "Language", "VoiceType", "Path"
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers =
arrayOf("Index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing soundbank
Clear()
// read each row and insert into database
val _soundbankList = ArrayList<Soundbank>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val description = row.getCell(1)?.stringCellValue ?: continue
val tag = row.getCell(2)?.stringCellValue ?: continue
val category = row.getCell(3)?.stringCellValue ?: continue
val language = row.getCell(4)?.stringCellValue ?: continue
val voiceType = row.getCell(5)?.stringCellValue ?: continue
val path = row.getCell(6)?.stringCellValue ?: continue
val soundbank = Soundbank(0u, description, tag, category, language, voiceType, path)
_soundbankList.add(soundbank)
}
return AddAll(_soundbankList)
} catch (e: Exception) {
Logger.error { "Error importing Soundbank, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("Soundbank")
val headerRow = sheet.createRow(0)
val headers =
arrayOf("Index", "Description", "TAG", "Category", "Language", "VoiceType", "Path")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("Description"))
row.createCell(2).setCellValue(resultSet.getString("TAG"))
row.createCell(3).setCellValue(resultSet.getString("Category"))
row.createCell(4).setCellValue(resultSet.getString("Language"))
row.createCell(5).setCellValue(resultSet.getString("VoiceType"))
row.createCell(6).setCellValue(resultSet.getString("Path"))
}
for (i in 0 until headers.size) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting Soundbank, Msg: ${e.message}" }
}
return null
}
/**
* Get all distinct airline code tags from soundbank
* @return a list of distinct airline code tags sorted alphabetically
*/
fun Get_AirlineCode_Tags(): List<String> {
return List
.filter { it.Category.equals(Category.Airline_Code.name,true) }
.distinctBy { it.TAG }
.map { it.TAG }
.sorted()
}
/**
* Get all distinct city tags from soundbank
* @return a list of distinct city tags sorted alphabetically
*/
fun Get_City_Tags(): List<String> {
return List
.filter { it.Category.equals(Category.City.name,true) }
.distinctBy { it.TAG }
.map { it.TAG }
.sorted()
}
fun Find_City_By_TAG(tag: String) : List<Soundbank> {
return List
.filter {it.Category.equals(Category.City.name,true) }
.filter { it.TAG.equals(tag, true) }
.distinctBy { it.TAG }
}
fun Find_AirlineName_By_TAG(tag: String) : List<Soundbank> {
return List
.filter {it.Category.equals(Category.Airplane_Name.name,true) }
.filter { it.TAG.equals(tag, true) }
.distinctBy { it.TAG }
}
fun Get_Places(): List<Soundbank> {
return List
.filter { it.Category.equals(Category.Places.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Shalat() : List<Soundbank> {
return List
.filter { it.Category.equals(Category.Shalat.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Sequences() : List<Soundbank> {
return List
.filter { it.Category.equals(Category.Sequence.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Reasons() : List<Soundbank> {
return List
.filter { it.Category.equals(Category.Reason.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Gates(): List<Soundbank> {
return List
.filter { it.Category.equals(Category.Gate.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Compensation(): List<Soundbank> {
return List
.filter { it.Category.equals(Category.Compensation.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Greeting() : List<Soundbank> {
return List
.filter { it.Category.equals(Category.Greeting.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
fun Get_Procedures(): List<Soundbank> {
return List
.filter { it.Category.equals(Category.Procedure.name,true) }
.distinctBy { it.TAG }
.sortedBy { it.TAG }
}
}

View File

@@ -0,0 +1,225 @@
package database.table
import database.data.UserDB
import database.dbFunctions
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.tinylog.Logger
import java.sql.Connection
import java.util.function.Consumer
class Table_Users(connection : Connection) : dbFunctions<UserDB>("newuser", connection, listOf("index", "username", "password", "location", "airline_tags", "city_tags", "messagebank_ann_id", "broadcastzones")) {
override fun Create() {
val tableDefinition = "CREATE TABLE IF NOT EXISTS ${super.dbName} (" +
"`index` INT AUTO_INCREMENT PRIMARY KEY," +
"username VARCHAR(100) NOT NULL," +
"password VARCHAR(100) NOT NULL," +
"location VARCHAR(100) NOT NULL," +
"airline_tags TEXT NOT NULL,"+ // Comma-separated soundbank tags
"city_tags TEXT NOT NULL,"+ // Comma-separated soundbank tags
"messagebank_ann_id TEXT NOT NULL,"+ // Comma-separated messagebank announcement index
"broadcastzones TEXT NOT NULL"+ // Comma-separated broadcast zones
")"
super.Create(tableDefinition)
}
override fun Get(cbOK: Consumer<Unit>?, cbFail: Consumer<String>?) {
List.clear()
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
while (resultSet?.next() == true) {
val user = UserDB(
resultSet.getLong("index").toUInt(),
resultSet.getString("username"),
resultSet.getString("password"),
resultSet.getString("location"),
resultSet.getString("airline_tags"),
resultSet.getString("city_tags"),
resultSet.getString("messagebank_ann_id"),
resultSet.getString("broadcastzones")
)
List.add(user)
}
cbOK?.accept(Unit)
} catch (e: Exception) {
Logger.error("Error fetching users: ${e.message}" as Any)
cbFail?.accept("Error fetching users: ${e.message}" )
}
}
override fun Add(data: UserDB): Boolean {
try {
val statement = connection.prepareStatement("INSERT INTO ${super.dbName} (username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?, ?,?, ?, ?)")
statement?.setString(1, data.username)
statement?.setString(2, data.password)
statement?.setString(3, data.location)
statement?.setString(4, data.airline_tags)
statement?.setString(5, data.city_tags)
statement?.setString(6, data.messagebank_ann_id)
statement?.setString(7, data.broadcastzones)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("User added: ${data.username}" as Any)
return true
} else {
Logger.warn("No user entry added for: ${data.username}" as Any)
}
} catch (e: Exception) {
Logger.error("Error adding user entry: ${e.message}" as Any)
}
return false
}
override fun AddAll(data: ArrayList<UserDB>): Boolean {
return try {
connection.autoCommit = false
val sql = "INSERT INTO ${super.dbName} (username, password, location,airline_tags,city_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?,?, ?, ?, ?)"
val statement = connection.prepareStatement(sql)
for (user in data) {
statement.setString(1, user.username)
statement.setString(2, user.password)
statement.setString(3, user.location)
statement.setString(4, user.airline_tags)
statement.setString(5, user.city_tags)
statement.setString(6, user.messagebank_ann_id)
statement.setString(7, user.broadcastzones)
statement.addBatch()
}
statement.executeBatch()
connection.commit()
Logger.info("Bulk user insert successful: ${data.size} entries" as Any)
connection.autoCommit = true
true
} catch (e: Exception) {
Logger.error("Error adding user entries: ${e.message}" as Any)
false
}
}
override fun UpdateByIndex(index: Int, data: UserDB): Boolean {
try {
val statement = connection.prepareStatement("UPDATE ${super.dbName} SET username = ?, password = ?, location = ?, airline_tags = ?,city_tags=?, messagebank_ann_id = ?, broadcastzones = ? WHERE `index` = ?")
statement?.setString(1, data.username)
statement?.setString(2, data.password)
statement?.setString(3, data.location)
statement?.setString(4, data.airline_tags)
statement?.setString(5, data.city_tags)
statement?.setString(6, data.messagebank_ann_id)
statement?.setString(7, data.broadcastzones)
statement?.setLong(8, index.toLong())
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info("User updated at index $index: ${data.username}" as Any)
return true
} else {
Logger.warn("No user entry updated at index $index for: ${data.username}" as Any)
}
} catch (e: Exception) {
Logger.error("Error updating user entry at index $index: ${e.message}" as Any)
}
return false
}
override fun Resort(): Boolean {
try {
val statement = connection.createStatement()
val tempdb_name = "temp_${super.dbName}"
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS $tempdb_name LIKE ${super.dbName}")
statement?.executeUpdate("TRUNCATE TABLE $tempdb_name")
statement?.executeUpdate("INSERT INTO $tempdb_name (username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones) SELECT username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones FROM ${super.dbName} ORDER BY username ")
statement?.executeUpdate("TRUNCATE TABLE ${super.dbName}")
statement?.executeUpdate("INSERT INTO ${super.dbName} (username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones) SELECT username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones FROM $tempdb_name")
statement?.executeUpdate("DROP TABLE $tempdb_name")
Logger.info("${super.dbName} table resorted by index" as Any)
// reload the local list
Get()
return true
} catch (e: Exception) {
Logger.error("Error resorting ${super.dbName} table by index: ${e.message}" as Any)
}
return false
}
override fun Import_XLSX(workbook: XSSFWorkbook): Boolean {
try {
val sheet = workbook.getSheet("User") ?: throw Exception("No sheet named 'User' found")
val headerRow = sheet.getRow(0) ?: throw Exception("No header row found")
val headers = arrayOf("Index", "username", "password", "location", "airline_tags", "city_tags", "messagebank_ann_id", "broadcastzones")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found")
if (cell.stringCellValue != header) throw Exception("Header '$header' not found")
}
// clear existing users
Clear()
// read each row and insert into database
val _userList = ArrayList<UserDB>()
for (rowIndex in 1..sheet.lastRowNum) {
val row = sheet.getRow(rowIndex) ?: continue
val username = row.getCell(1)?.stringCellValue ?: continue
val password = row.getCell(2)?.stringCellValue ?: continue
val location = row.getCell(3)?.stringCellValue ?: continue
val airline_tags = row.getCell(4)?.stringCellValue ?: continue
val city_tags = row.getCell(5)?.stringCellValue ?: continue
val messagebank_ann_id = row.getCell(6)?.stringCellValue ?: continue
val broadcastzones = row.getCell(7)?.stringCellValue ?: continue
val user = UserDB(
0u,
username,
password,
location,
airline_tags,
city_tags,
messagebank_ann_id,
broadcastzones
)
_userList.add(user)
}
return AddAll(_userList)
} catch (e: Exception) {
Logger.error { "Error importing User, Msg: ${e.message}" }
}
return false
}
override fun Export_XLSX(): XSSFWorkbook? {
try {
val statement = connection.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM ${super.dbName}")
val workbook = XSSFWorkbook()
val sheet = workbook.createSheet("User")
val headerRow = sheet.createRow(0)
val headers = arrayOf("Index", "username", "password", "location", "airline_tags","city_tags", "messagebank_ann_id", "broadcastzones")
for ((colIndex, header) in headers.withIndex()) {
val cell = headerRow.createCell(colIndex)
cell.setCellValue(header)
}
var rowIndex = 1
while (resultSet?.next() == true) {
val row = sheet.createRow(rowIndex++)
row.createCell(0).setCellValue(resultSet.getString("index"))
row.createCell(1).setCellValue(resultSet.getString("username"))
row.createCell(2).setCellValue(resultSet.getString("password"))
row.createCell(3).setCellValue(resultSet.getString("location"))
row.createCell(4).setCellValue(resultSet.getString("airline_tags"))
row.createCell(5).setCellValue(resultSet.getString("city_tags"))
row.createCell(6).setCellValue(resultSet.getString("messagebank_ann_id"))
row.createCell(7).setCellValue(resultSet.getString("broadcastzones"))
}
for (i in headers.indices) {
sheet.autoSizeColumn(i)
}
return workbook
} catch (e: Exception) {
Logger.error { "Error exporting User, Msg: ${e.message}" }
}
return null
}
/**
* Check if a username already exists in the userDB (case-insensitive)
*/
fun Username_exists(username: String): Boolean {
return List.any { it.username.equals(username, ignoreCase = true) }
}
}

View File

@@ -9,7 +9,7 @@ import com.google.cloud.texttospeech.v1.VoiceSelectionParams
import content.Category import content.Category
import content.Language import content.Language
import content.VoiceType import content.VoiceType
import database.Soundbank import database.data.Soundbank
import org.tinylog.Logger import org.tinylog.Logger
import java.nio.file.Files import java.nio.file.Files
import java.util.function.BiConsumer import java.util.function.BiConsumer

View File

@@ -24,14 +24,14 @@ import content.Category
import content.Language import content.Language
import content.ScheduleDay import content.ScheduleDay
import content.VoiceType import content.VoiceType
import database.BroadcastZones import database.data.BroadcastZones
import database.LanguageLink import database.data.LanguageLink
import database.MariaDB import database.MariaDB
import database.Messagebank import database.data.Messagebank
import database.ScheduleBank import database.data.ScheduleBank
import database.SoundChannel import database.data.SoundChannel
import database.Soundbank import database.data.Soundbank
import database.UserDB import database.data.UserDB
import db import db
import io.javalin.Javalin import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder.* import io.javalin.apibuilder.ApiBuilder.*
@@ -43,8 +43,8 @@ import java.nio.file.Files
import java.time.LocalDateTime import java.time.LocalDateTime
import codes.configKeys import codes.configKeys
import config import config
import database.LogSemiauto import database.data.LogSemiauto
import database.QueueTable import database.data.QueueTable
import google.GoogleTTS import google.GoogleTTS
import google.autoadd import google.autoadd
import google.fileoperation import google.fileoperation
@@ -152,6 +152,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
"getAppVersion" -> { "getAppVersion" -> {
SendReply(wsMessageContext, cmd.command, version) SendReply(wsMessageContext, cmd.command, version)
} }
"getSystemTime" -> { "getSystemTime" -> {
val systemtime = LocalDateTime.now().format(datetimeformat1) val systemtime = LocalDateTime.now().format(datetimeformat1)
@@ -184,11 +185,19 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
"getMemoryStatus" -> { "getMemoryStatus" -> {
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(Somecodes.getMemoryUsage())) SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(Somecodes.getMemoryUsage())
)
} }
"getDiskStatus" -> { "getDiskStatus" -> {
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(Somecodes.getDiskUsage())) SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(Somecodes.getDiskUsage())
)
} }
"getNetworkStatus" -> { "getNetworkStatus" -> {
@@ -233,16 +242,22 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val fop = js.get("fileoperation")?.asText("overwrite") ?: "overwrite" val fop = js.get("fileoperation")?.asText("overwrite") ?: "overwrite"
val aa = js.get("autoadd")?.asText("add") ?: "add" val aa = js.get("autoadd")?.asText("add") ?: "add"
Logger.info { "Starting TTS Soundbank Generation, VoiceType=$voicetype, Language" } Logger.info { "Starting TTS Soundbank Generation, VoiceType=$voicetype, Language" }
ttsjob.GenerateSoundbank(voicetype, Language.from_GoogleTTSLanguage(languagecode), ttsjob.GenerateSoundbank(
voicetype, Language.from_GoogleTTSLanguage(languagecode),
VoiceType.fromString(databasesource), VoiceType.fromString(databasesource),
VoiceType.fromString(targetas), fileoperation.fromString(fop), VoiceType.fromString(targetas), fileoperation.fromString(fop),
autoadd.fromString(aa)){ progress, message -> autoadd.fromString(aa)
SendReply(wsMessageContext, "tts_generate_progress", objectmapper.writeValueAsString( ) { progress, message ->
SendReply(
wsMessageContext,
"tts_generate_progress",
objectmapper.writeValueAsString(
mapOf( mapOf(
"progress" to progress, "progress" to progress,
"message" to message "message" to message
) )
)) )
)
} }
} }
@@ -311,11 +326,19 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
"getMemoryStatus" -> { "getMemoryStatus" -> {
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(Somecodes.getMemoryUsage())) SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(Somecodes.getMemoryUsage())
)
} }
"getDiskStatus" -> { "getDiskStatus" -> {
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(Somecodes.getDiskUsage())) SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(Somecodes.getDiskUsage())
)
} }
"getNetworkStatus" -> { "getNetworkStatus" -> {
@@ -465,7 +488,10 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val prev = WsContextMap[key] val prev = WsContextMap[key]
if (prev != null) { if (prev != null) {
prev.bc?.Remove_Mp3_Consumer(key) prev.bc?.Remove_Mp3_Consumer(key)
prev.ws?.closeSession(WsCloseStatus.NORMAL_CLOSURE, "Reopen Live Audio Stream") prev.ws?.closeSession(
WsCloseStatus.NORMAL_CLOSURE,
"Reopen Live Audio Stream"
)
} }
WsContextMap.remove(key) WsContextMap.remove(key)
ctx.cookie("client-stream-id", "") ctx.cookie("client-stream-id", "")
@@ -483,7 +509,10 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val prev = WsContextMap[key] val prev = WsContextMap[key]
if (prev != null) { if (prev != null) {
prev.bc?.Remove_Mp3_Consumer(key) prev.bc?.Remove_Mp3_Consumer(key)
prev.ws?.closeSession(WsCloseStatus.NORMAL_CLOSURE, "Close Live Audio Stream") prev.ws?.closeSession(
WsCloseStatus.NORMAL_CLOSURE,
"Close Live Audio Stream"
)
} }
WsContextMap.remove(key) WsContextMap.remove(key)
ctx.cookie("client-stream-id", "") ctx.cookie("client-stream-id", "")
@@ -623,7 +652,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
.result(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) .result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
} }
get("AirlineTags") { ctx -> get("AirlineTags") { ctx ->
val tags = db.Get_AirlineCode_Tags() val tags = db.soundDB.Get_AirlineCode_Tags()
val value = db.soundDB.List val value = db.soundDB.List
.asSequence() .asSequence()
.filter { f1 -> f1.Category.equals(Category.Airplane_Name.name, true) } .filter { f1 -> f1.Category.equals(Category.Airplane_Name.name, true) }
@@ -867,7 +896,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
message_detail, message_detail,
message_tags message_tags
) )
val existed = db.messageDB.List.any{ it.ANN_ID== mb.ANN_ID && it.Language == mb.Language && it.Voice_Type == mb.Voice_Type } val existed =
db.messageDB.List.any { it.ANN_ID == mb.ANN_ID && it.Language == mb.Language && it.Voice_Type == mb.Voice_Type }
if (!existed) { if (!existed) {
if (db.messageDB.Add(mb)) { if (db.messageDB.Add(mb)) {
db.messageDB.Resort() db.messageDB.Resort()
@@ -1026,11 +1056,21 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
db.languageDB.Get({ db.languageDB.Get({
// get language link list // get language link list
ctx.result(MariaDB.ArrayListtoString(db.languageDB.List)) ctx.result(MariaDB.ArrayListtoString(db.languageDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
}
post("DefaultInit") { ctx ->
// clear languageDB and init with default values
// default value : every CITY in soundDB will have language linked to
db.languageDB.Clear()
db.soundDB.Get_City_Tags().forEach { city ->
val newvalue = LanguageLink(0u, city, Language.DefaultLanguageLink())
db.languageDB.Add(newvalue)
}
db.languageDB.Resort()
} }
post("Add") { post("Add") {
// Parse JSON from request body // Parse JSON from request body
@@ -1179,8 +1219,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
db.scheduleDB.Get({ db.scheduleDB.Get({
// get timer list // get timer list
ctx.result(MariaDB.ArrayListtoString(db.scheduleDB.List)) ctx.result(MariaDB.ArrayListtoString(db.scheduleDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
// get timer list // get timer list
@@ -1388,8 +1427,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
get("List") { ctx -> get("List") { ctx ->
db.userDB.Get({ db.userDB.Get({
ctx.result(objectmapper.writeValueAsString(db.userDB.List)) ctx.result(objectmapper.writeValueAsString(db.userDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
@@ -1416,15 +1454,14 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
// city, airline, messagebank_ann_id boleh kosong, untuk user yang paging saja // city, airline, messagebank_ann_id boleh kosong, untuk user yang paging saja
// location juga optional // location juga optional
// yang wajib ada adalah username, password, broadcastzones // yang wajib ada adalah username, password, broadcastzones
if (ValidStrings(username, password, broadcastzones )) if (ValidStrings(username, password, broadcastzones)) {
{ if (!db.userDB.Username_exists(username)) {
if (!db.Username_exists(username)) {
if (ValidString(airline_tags)) { if (ValidString(airline_tags)) {
// ada airline_tags, berarti harus di cek apakah ada di table soundbank // ada airline_tags, berarti harus di cek apakah ada di table soundbank
// kalau tidak ada airline_tags, tidak perlu cek // kalau tidak ada airline_tags, tidak perlu cek
val atags = airline_tags.split(";").map { it.trim() } val atags = airline_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val airlinetags = db.Get_AirlineCode_Tags() val airlinetags = db.soundDB.Get_AirlineCode_Tags()
val missing_airlinetags = ArrayList<String>() val missing_airlinetags = ArrayList<String>()
atags.forEach { tag -> atags.forEach { tag ->
if (!airlinetags.any { it.equals(tag, true) }) { if (!airlinetags.any { it.equals(tag, true) }) {
@@ -1433,7 +1470,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_airlinetags.isNotEmpty()) { if (missing_airlinetags.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Airline tags not found in soundbank: ${missing_airlinetags.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"Airline tags not found in soundbank: ${
missing_airlinetags.joinToString(
", "
)
}"
)
)
)
return@post return@post
} }
} }
@@ -1442,7 +1489,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
// kalau tidak ada city_tags, tidak perlu cek // kalau tidak ada city_tags, tidak perlu cek
val ctags = city_tags.split(";").map { it.trim() } val ctags = city_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val citytags = db.Get_City_Tags() val citytags = db.soundDB.Get_City_Tags()
val missing_citytags = ArrayList<String>() val missing_citytags = ArrayList<String>()
ctags.forEach { tag -> ctags.forEach { tag ->
if (!citytags.any { it.equals(tag, true) }) { if (!citytags.any { it.equals(tag, true) }) {
@@ -1451,7 +1498,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_citytags.isNotEmpty()) { if (missing_citytags.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("City tags not found in soundbank: ${missing_citytags.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"City tags not found in soundbank: ${
missing_citytags.joinToString(
", "
)
}"
)
)
)
return@post return@post
} }
@@ -1463,7 +1520,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
.map { it.trim() } .map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
.mapNotNull { it.toUIntOrNull() } .mapNotNull { it.toUIntOrNull() }
val mbankids = db.Get_MessageID_List() val mbankids = db.messageDB.Get_MessageID_List()
if (!mbids.all { id -> mbankids.any { it == id } }) { if (!mbids.all { id -> mbankids.any { it == id } }) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Some ANN_ID not found in Messagebank"))) .result(objectmapper.writeValueAsString(resultMessage("Some ANN_ID not found in Messagebank")))
@@ -1475,7 +1532,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val bzdesc = val bzdesc =
broadcastzones.split(";").map { it.trim() } broadcastzones.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val bzlist = db.Get_BroadcastZone_List() val bzlist = db.broadcastDB.Get_BroadcastZone_List()
val missing_broadcastzones = ArrayList<String>() val missing_broadcastzones = ArrayList<String>()
bzdesc.forEach { bz -> bzdesc.forEach { bz ->
if (!bzlist.any { it.equals(bz, true) }) { if (!bzlist.any { it.equals(bz, true) }) {
@@ -1484,7 +1541,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_broadcastzones.isNotEmpty()) { if (missing_broadcastzones.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Broadcast zone tags not found in soundbank: ${missing_broadcastzones.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"Broadcast zone tags not found in soundbank: ${
missing_broadcastzones.joinToString(
", "
)
}"
)
)
)
return@post return@post
} }
@@ -1546,8 +1613,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
// city, airline, messagebank_ann_id boleh kosong, untuk user yang paging saja // city, airline, messagebank_ann_id boleh kosong, untuk user yang paging saja
// location juga optional // location juga optional
// yang wajib ada adalah username, password, broadcastzones // yang wajib ada adalah username, password, broadcastzones
if (ValidStrings(_username, _password, _broadcastzones)) if (ValidStrings(_username, _password, _broadcastzones)) {
{
val _otherusername = db.userDB.List.find { xx -> val _otherusername = db.userDB.List.find { xx ->
xx.username.equals( xx.username.equals(
_username, _username,
@@ -1569,7 +1635,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
// kalau tidak ada airline_tags, tidak perlu cek // kalau tidak ada airline_tags, tidak perlu cek
val atags = _airline_tags.split(";").map { it.trim() } val atags = _airline_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val airlinetags = db.Get_AirlineCode_Tags() val airlinetags = db.soundDB.Get_AirlineCode_Tags()
val missing_airlinetags = ArrayList<String>() val missing_airlinetags = ArrayList<String>()
atags.forEach { tag -> atags.forEach { tag ->
if (!airlinetags.any { it.equals(tag, true) }) { if (!airlinetags.any { it.equals(tag, true) }) {
@@ -1578,7 +1644,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_airlinetags.isNotEmpty()) { if (missing_airlinetags.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Airline tags not found in soundbank: ${missing_airlinetags.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"Airline tags not found in soundbank: ${
missing_airlinetags.joinToString(
", "
)
}"
)
)
)
return@patch return@patch
} }
@@ -1588,15 +1664,26 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
// kalau tidak ada city_tags, tidak perlu cek // kalau tidak ada city_tags, tidak perlu cek
val ctags = _city_tags.split(";").map { it.trim() } val ctags = _city_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val citytags = db.Get_City_Tags() val citytags = db.soundDB.Get_City_Tags()
val missing_citytags = ArrayList<String>() val missing_citytags = ArrayList<String>()
ctags.forEach { tag -> ctags.forEach { tag ->
if (!citytags.any { it.equals(tag, true) }) { if (!citytags.any { it.equals(tag, true) }) {
missing_citytags.add(tag) missing_citytags.add(tag)
} }
} }
if (missing_citytags.isNotEmpty()){ ctx.status(400) if (missing_citytags.isNotEmpty()) {
.result(objectmapper.writeValueAsString(resultMessage("City tags not found in soundbank: ${missing_citytags.joinToString(", ")}"))) ctx.status(400)
.result(
objectmapper.writeValueAsString(
resultMessage(
"City tags not found in soundbank: ${
missing_citytags.joinToString(
", "
)
}"
)
)
)
return@patch return@patch
} }
@@ -1608,7 +1695,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
.map { it.trim() } .map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
.mapNotNull { it.toUIntOrNull() } .mapNotNull { it.toUIntOrNull() }
val mbankids = db.Get_MessageID_List() val mbankids = db.messageDB.Get_MessageID_List()
val missing_broadcastids = ArrayList<UInt>() val missing_broadcastids = ArrayList<UInt>()
mbids.forEach { mbid -> mbids.forEach { mbid ->
if (!mbankids.any { it == mbid }) { if (!mbankids.any { it == mbid }) {
@@ -1617,7 +1704,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_broadcastids.isNotEmpty()) { if (missing_broadcastids.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("ANN_ID not found in Messagebank: ${missing_broadcastids.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"ANN_ID not found in Messagebank: ${
missing_broadcastids.joinToString(
", "
)
}"
)
)
)
return@patch return@patch
} }
@@ -1625,7 +1722,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val bzdesc = _broadcastzones.split(";").map { it.trim() } val bzdesc = _broadcastzones.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct() .filter { it.isNotEmpty() }.distinct()
val bzlist = db.Get_BroadcastZone_List() val bzlist = db.broadcastDB.Get_BroadcastZone_List()
val missing_broadcastzones = ArrayList<String>() val missing_broadcastzones = ArrayList<String>()
bzdesc.forEach { bz -> bzdesc.forEach { bz ->
if (!bzlist.any { it.equals(bz, true) }) { if (!bzlist.any { it.equals(bz, true) }) {
@@ -1634,7 +1731,17 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
if (missing_broadcastzones.isNotEmpty()) { if (missing_broadcastzones.isNotEmpty()) {
ctx.status(400) ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Broadcast zone tags not found in soundbank: ${missing_broadcastzones.joinToString(", ")}"))) .result(
objectmapper.writeValueAsString(
resultMessage(
"Broadcast zone tags not found in soundbank: ${
missing_broadcastzones.joinToString(
", "
)
}"
)
)
)
return@patch return@patch
} }
@@ -1741,9 +1848,9 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val logfilter = get1.queryParam("filter") ?: "" val logfilter = get1.queryParam("filter") ?: ""
if (ValiDateForLogHtml(logdate)) { if (ValiDateForLogHtml(logdate)) {
val xlsxdata = if (ValidString(logfilter)) { val xlsxdata = if (ValidString(logfilter)) {
db.Export_Log_XLSX(logdate.replace('-', '/'), logfilter) db.logDB.Export_Log_XLSX(logdate.replace('-', '/'), logfilter)
} else { } else {
db.Export_Log_XLSX(logdate.replace('-', '/'), "") db.logDB.Export_Log_XLSX(logdate.replace('-', '/'), "")
} }
if (xlsxdata != null) { if (xlsxdata != null) {
get1.header( get1.header(
@@ -1766,8 +1873,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
get("List") { ctx -> get("List") { ctx ->
db.broadcastDB.Get({ db.broadcastDB.Get({
ctx.result(MariaDB.ArrayListtoString(db.broadcastDB.List)) ctx.result(MariaDB.ArrayListtoString(db.broadcastDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
} }
@@ -1924,14 +2030,13 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
get("List") { ctx -> get("List") { ctx ->
db.soundchannelDB.Get({ db.soundchannelDB.Get({
ctx.result(MariaDB.ArrayListtoString(db.soundchannelDB.List)) ctx.result(MariaDB.ArrayListtoString(db.soundchannelDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
} }
get("SoundChannelDescriptions") { get("SoundChannelDescriptions") {
it.result(objectmapper.writeValueAsString(db.Get_SoundChannel_List())) it.result(objectmapper.writeValueAsString(db.soundchannelDB.Get_SoundChannel_List()))
} }
delete("List") { delete("List") {
// truncate sound channel table // truncate sound channel table
@@ -2060,8 +2165,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
get("List") { ctx -> get("List") { ctx ->
db.queuepagingDB.Get({ db.queuepagingDB.Get({
ctx.result(MariaDB.ArrayListtoString(db.queuepagingDB.List)) ctx.result(MariaDB.ArrayListtoString(db.queuepagingDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
@@ -2099,8 +2203,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
get("List") { ctx -> get("List") { ctx ->
db.queuetableDB.Get({ db.queuetableDB.Get({
ctx.result(MariaDB.ArrayListtoString(db.queuetableDB.List)) ctx.result(MariaDB.ArrayListtoString(db.queuetableDB.List))
},{ }, { msgFail ->
msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail))) ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
}) })
@@ -2443,8 +2546,14 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
Logger.info { "Changed Web Access Passwords" } Logger.info { "Changed Web Access Passwords" }
// update userlist // update userlist
userlist = listOf( userlist = listOf(
Pair(_config.Get(configKeys.WEBAPP_ADMIN_USERNAME.key), _config.Get(configKeys.WEBAPP_ADMIN_PASSWORD.key)), Pair(
Pair(_config.Get(configKeys.WEBAPP_VIEWER_USERNAME.key), _config.Get(configKeys.WEBAPP_VIEWER_PASSWORD.key)) _config.Get(configKeys.WEBAPP_ADMIN_USERNAME.key),
_config.Get(configKeys.WEBAPP_ADMIN_PASSWORD.key)
),
Pair(
_config.Get(configKeys.WEBAPP_VIEWER_USERNAME.key),
_config.Get(configKeys.WEBAPP_VIEWER_PASSWORD.key)
)
) )
it.result(objectmapper.writeValueAsString(resultMessage("OK"))) it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
@@ -2494,7 +2603,12 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
it.cookie("semiauto-user", user.username) it.cookie("semiauto-user", user.username)
it.redirect("index.html") it.redirect("index.html")
db.logSemiAuto.Add(LogSemiauto.NewLog("SEMIAUTOWEB", "User logged in: ${user.username} from ip ${it.ip()}")) db.logSemiAuto.Add(
LogSemiauto.NewLog(
"SEMIAUTOWEB",
"User logged in: ${user.username} from ip ${it.ip()}"
)
)
} else ResultMessageString(it, 400, "Invalid username or password") } else ResultMessageString(it, 400, "Invalid username or password")
} else ResultMessageString(it, 400, "Username or password cannot be empty") } else ResultMessageString(it, 400, "Username or password cannot be empty")
} }
@@ -2580,7 +2694,12 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
ctx.result(objectmapper.writeValueAsString(result)) ctx.result(objectmapper.writeValueAsString(result))
db.logSemiAuto.Add(LogSemiauto.NewLog("SEMIAUTOWEB", "Initialized Web variables for user: ${user.username}")) db.logSemiAuto.Add(
LogSemiauto.NewLog(
"SEMIAUTOWEB",
"Initialized Web variables for user: ${user.username}"
)
)
} else ResultMessageString(ctx, 400, "User not found") } else ResultMessageString(ctx, 400, "User not found")
} else ResultMessageString(ctx, 400, "Username is empty") } else ResultMessageString(ctx, 400, "Username is empty")
} }
@@ -2612,7 +2731,12 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
db.queuetableDB.Resort() db.queuetableDB.Resort()
Logger.info { "SemiAutoWeb added to queue table: $qt" } Logger.info { "SemiAutoWeb added to queue table: $qt" }
ctx.result(objectmapper.writeValueAsString(resultMessage("OK"))) ctx.result(objectmapper.writeValueAsString(resultMessage("OK")))
db.logSemiAuto.Add(LogSemiauto.NewLog("SEMIAUTOWEB", "Added to queue table: $qt")) db.logSemiAuto.Add(
LogSemiauto.NewLog(
"SEMIAUTOWEB",
"Added to queue table: $qt"
)
)
} else ResultMessageString(ctx, 500, "Failed to add to queue table") } else ResultMessageString(ctx, 500, "Failed to add to queue table")
} else ResultMessageString(ctx, 400, "Broadcast zones cannot be empty") } else ResultMessageString(ctx, 400, "Broadcast zones cannot be empty")
} else ResultMessageString(ctx, 400, "Tags cannot be empty") } else ResultMessageString(ctx, 400, "Tags cannot be empty")
@@ -2626,9 +2750,9 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val logfilter = get1.queryParam("filter") ?: "" val logfilter = get1.queryParam("filter") ?: ""
if (ValiDateForLogHtml(logdate)) { if (ValiDateForLogHtml(logdate)) {
val xlsxdata = if (ValidString(logfilter)) { val xlsxdata = if (ValidString(logfilter)) {
db.Export_Log_XLSX(logdate.replace('-', '/'), logfilter) db.logDB.Export_Log_XLSX(logdate.replace('-', '/'), logfilter)
} else { } else {
db.Export_Log_XLSX(logdate.replace('-', '/'), "") db.logDB.Export_Log_XLSX(logdate.replace('-', '/'), "")
} }
if (xlsxdata != null) { if (xlsxdata != null) {
get1.header( get1.header(
@@ -2698,7 +2822,6 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
} }
fun Get_Barix_Connection_by_ZoneName(zonename: String): BarixConnection? { fun Get_Barix_Connection_by_ZoneName(zonename: String): BarixConnection? {
if (ValidString(zonename)) { if (ValidString(zonename)) {
val bz = db.broadcastDB.List.find { it.description == zonename } val bz = db.broadcastDB.List.find { it.description == zonename }