380 lines
14 KiB
Kotlin
380 lines
14 KiB
Kotlin
package codes
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode
|
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
import content.ScheduleDay
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import oshi.SystemInfo
|
|
import oshi.hardware.CentralProcessor
|
|
import oshi.hardware.GlobalMemory
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
import java.time.LocalDateTime
|
|
import java.time.format.DateTimeFormatter
|
|
import java.util.function.Consumer
|
|
import kotlin.io.path.name
|
|
|
|
|
|
@Suppress("unused")
|
|
class Somecodes {
|
|
companion object {
|
|
val current_directory : String = System.getProperty("user.dir")
|
|
val SoundbankResult_directory : Path = Path.of(current_directory,"SoundbankResult")
|
|
val PagingResult_directory : Path = Path.of(current_directory,"PagingResult")
|
|
val si = SystemInfo()
|
|
val processor: CentralProcessor = si.hardware.processor
|
|
val memory : GlobalMemory = si.hardware.memory
|
|
val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
|
|
val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
|
|
val dateformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
|
|
val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss")
|
|
val timeformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm")
|
|
val filenameformat: DateTimeFormatter = DateTimeFormatter.ofPattern("ddMMyyyy_HHmmss")
|
|
const val KB_threshold = 1024.0
|
|
const val MB_threshold = KB_threshold * 1024.0
|
|
const val GB_threshold = MB_threshold * 1024.0
|
|
const val TB_threshold = GB_threshold * 1024.0
|
|
val objectmapper = jacksonObjectMapper()
|
|
|
|
// regex for getting ann_id from Message, which is the number inside []
|
|
private val ann_id_regex = Regex("\\[(\\d+)]")
|
|
|
|
/**
|
|
* Check if a string is a valid number.
|
|
*/
|
|
fun IsNumber(value: String) : Boolean {
|
|
return value.toIntOrNull() != null
|
|
}
|
|
|
|
/**
|
|
* Check if a string is alphabetic (contains only letters).
|
|
*/
|
|
fun IsAlphabethic(value: String) : Boolean {
|
|
return value.all { it.isLetter() }
|
|
}
|
|
|
|
/**
|
|
* Extract ANN ID from a message string.
|
|
* The ANN ID is expected to be a number enclosed in square brackets (e.g., "[123]").
|
|
* @param message The message string to extract the ANN ID from.
|
|
* @return The extracted ANN ID as an integer, or -1 if not found or invalid.
|
|
*/
|
|
fun Get_ANN_ID(message: String) : Int {
|
|
val matchResult = ann_id_regex.find(message)
|
|
return matchResult?.groups?.get(1)?.value?.toInt() ?: -1
|
|
}
|
|
|
|
/**
|
|
* Convert an object to a JSON string.
|
|
* @param data The object to convert.
|
|
* @return A JSON string representation of the object, or "{}" if conversion fails.
|
|
*/
|
|
fun toJsonString(data: Any) : String {
|
|
return try {
|
|
objectmapper.writeValueAsString(data)
|
|
} catch (e: Exception){
|
|
"{}"
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a JSON string to an object of the specified class.
|
|
* @param json The JSON string to convert.
|
|
* @param clazz The class of the object to convert to.
|
|
* @return An object of the specified class, or null if conversion fails.
|
|
*/
|
|
fun <T> fromJsonString(json: String, clazz: Class<T>) : T? {
|
|
return try {
|
|
objectmapper.readValue(json, clazz)
|
|
} catch (e: Exception){
|
|
null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a JSON string to a JsonNode.
|
|
* @param data The JSON string to convert.
|
|
* @return A JsonNode representation of the JSON string, or empty JsonNode if conversion fails.
|
|
*/
|
|
fun toJsonNode(data: String) : JsonNode {
|
|
return try {
|
|
objectmapper.readTree(data)
|
|
} catch (e: Exception){
|
|
objectmapper.createObjectNode()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* List all audio files (.mp3 and .wav) in the specified directory and its subdirectories.
|
|
* Only files larger than 1KB are included.
|
|
* @param dir The directory to search in (default is the current working directory).
|
|
* @return A list of absolute paths to the audio files found.
|
|
*/
|
|
fun ListAudioFiles(dir: String = current_directory) : List<String>{
|
|
return try{
|
|
// find all files that ends with .mp3 or .wav
|
|
// and find them recursively
|
|
val p = Path.of(dir)
|
|
if (Files.exists(p) && Files.isDirectory(p)){
|
|
Files.walk(p)
|
|
// cari file regular saja
|
|
.filter { Files.isRegularFile(it)}
|
|
// size lebih dari 1KB
|
|
.filter { Files.size(it) > 1024}
|
|
// extension .mp3 atau .wav
|
|
.filter { it.name.endsWith(".mp3",true) || it.name.endsWith(".wav",true) }
|
|
.map { it.toAbsolutePath().toString() }
|
|
.toList()
|
|
} else throw Exception()
|
|
|
|
} catch (_ : Exception){
|
|
emptyList()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts a size in bytes to a human-readable format.
|
|
* @param size Size in bytes.
|
|
* @return A string representing the size in a human-readable format.
|
|
*/
|
|
fun SizetoHuman(size: Long): String {
|
|
return when {
|
|
size < KB_threshold -> "${size}B"
|
|
size < MB_threshold -> String.format("%.2f KB", size / KB_threshold)
|
|
size < GB_threshold -> String.format("%.2f MB", size / MB_threshold)
|
|
size < TB_threshold -> String.format("%.2f GB", size / GB_threshold)
|
|
else -> String.format("%.2f TB", size / TB_threshold)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Disk usage using OSHI library.
|
|
* @param path The path to check disk usage, defaults to the current working directory.
|
|
* @return A string representing the disk usage of the file system in a human-readable format.
|
|
*/
|
|
fun getDiskUsage(path: String = current_directory) : String {
|
|
return try{
|
|
val p = Path.of(path).toFile()
|
|
if (p.exists() && p.isDirectory){
|
|
val total = p.totalSpace
|
|
val free = p.freeSpace
|
|
val used = total - free
|
|
String.format("Total: %s, Used: %s, Free: %s, Usage: %.2f%%",
|
|
SizetoHuman(total),
|
|
SizetoHuman(used),
|
|
SizetoHuman(free),
|
|
(used.toDouble() / total * 100)
|
|
)
|
|
} else throw Exception()
|
|
|
|
} catch (_ : Exception){
|
|
"N/A"
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get CPU usage using OSHI library.
|
|
* @param cb A callback function that receives the CPU usage as a string.
|
|
*/
|
|
fun getCPUUsage(cb : Consumer<String>){
|
|
CoroutineScope(Dispatchers.Default).launch {
|
|
val prev = processor.systemCpuLoadTicks
|
|
delay(1000)
|
|
val current = processor.systemCpuLoadTicks
|
|
|
|
fun delta(t: CentralProcessor.TickType) = current[t.index] - prev[t.index]
|
|
|
|
val idle = delta(CentralProcessor.TickType.IDLE) + delta(CentralProcessor.TickType.IOWAIT)
|
|
val busy = delta(CentralProcessor.TickType.USER) + delta(CentralProcessor.TickType.SYSTEM) +
|
|
delta(CentralProcessor.TickType.NICE) + delta(CentralProcessor.TickType.IRQ) +
|
|
delta(CentralProcessor.TickType.SOFTIRQ)+ delta(CentralProcessor.TickType.STEAL)
|
|
|
|
val total = idle + busy
|
|
val usage = if (total > 0) {
|
|
(busy.toDouble() / total) * 100
|
|
} else {
|
|
0.0
|
|
}
|
|
cb.accept(String.format("%.2f%%", usage))
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Get RAM usage using OSHI library.
|
|
* @return A string representing the total, used, and available memory in a human-readable format.
|
|
*/
|
|
fun getMemoryUsage() : String{
|
|
val totalMemory = memory.total
|
|
val availableMemory = memory.available
|
|
val usedMemory = totalMemory - availableMemory
|
|
return String.format("Total: %s, Used: %s, Available: %s, Usage: %.2f%%",
|
|
SizetoHuman(totalMemory),
|
|
SizetoHuman(usedMemory),
|
|
SizetoHuman(availableMemory)
|
|
, (usedMemory.toDouble() / totalMemory * 100))
|
|
}
|
|
|
|
/**
|
|
* Check if a value is a valid non-blank string.
|
|
* @param value The value to check.
|
|
* @return True if the value is a non-blank string, false otherwise.
|
|
*/
|
|
fun ValidString(value: Any) : Boolean {
|
|
return value is String && value.isNotBlank()
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid file path and the file exists.
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid file path, false otherwise.
|
|
*/
|
|
fun ValidFile(value : String) : Boolean {
|
|
if (value.isNotBlank()){
|
|
return Files.exists(Path.of(value))
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid date in the format "dd/MM/yyyy".
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid date, false otherwise.
|
|
*/
|
|
fun ValidDate(value: String): Boolean{
|
|
return try{
|
|
if (ValidString(value)){
|
|
dateformat1.parse(value)
|
|
true
|
|
} else throw Exception()
|
|
|
|
} catch (_: Exception){
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid IPv4 address.
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid IPv4 address, false otherwise.
|
|
*/
|
|
fun ValidIPV4(value: String): Boolean{
|
|
return try{
|
|
if (ValidString(value)){
|
|
val parts = value.split(".")
|
|
if (parts.size != 4) return false
|
|
for (part in parts){
|
|
val num = part.toInt()
|
|
if (num !in 0..255) return false
|
|
}
|
|
true
|
|
} else throw Exception()
|
|
|
|
} catch (_: Exception){
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid date in the format "dd-MM-yyyy".
|
|
* This format is used for log HTML files.
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid date, false otherwise.
|
|
*/
|
|
fun ValiDateForLogHtml(value: String): Boolean{
|
|
return try{
|
|
if (ValidString(value)){
|
|
dateformat2.parse(value)
|
|
true
|
|
} else throw Exception()
|
|
|
|
} catch (_: Exception){
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid time in the format "hh:mm:ss".
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid time, false otherwise.
|
|
*/
|
|
fun ValidTime(value: String): Boolean{
|
|
return try{
|
|
if (ValidString(value)){
|
|
timeformat1.parse(value)
|
|
true
|
|
} else throw Exception()
|
|
|
|
} catch (_: Exception){
|
|
false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid schedule time in the format "HH:mm".
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid schedule time, false otherwise.
|
|
*/
|
|
fun ValidScheduleTime(value: String): Boolean{
|
|
// format HH:mm
|
|
try {
|
|
if (ValidString(value)){
|
|
timeformat2.parse(value)
|
|
return true
|
|
}
|
|
} catch (_ : Exception){
|
|
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Find a schedule day by its name.
|
|
* @param value The name of the schedule day to find.
|
|
* @return The name of the schedule day if found, null otherwise.
|
|
*/
|
|
fun FindScheduleDay(value: String) : String? {
|
|
val sd = ScheduleDay.entries.find { sd -> sd.name == value }
|
|
return sd?.name
|
|
}
|
|
|
|
/**
|
|
* Check if a string is a valid schedule day or a valid date.
|
|
* A valid schedule day is either one of the ScheduleDay enum names or a date in the format "dd/MM/yyyy".
|
|
* @param value The string to check.
|
|
* @return True if the string is a valid schedule day or date, false otherwise.
|
|
*/
|
|
fun ValidScheduleDay(value: String) : Boolean {
|
|
if (ValidString(value)){
|
|
// check if value is one of ScheduleDay enum name
|
|
if (FindScheduleDay(value) != null){
|
|
return true
|
|
}
|
|
// check if value is in format dd/MM/yyyy
|
|
return ValidDate(value)
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Generate a WAV file name with the current date and time.
|
|
* The file name format is: [prefix]_ddMMyyyy_HHmmss_[postfix].wav
|
|
* @param prefix An optional prefix to add before the date and time.
|
|
* @param postfix An optional postfix to add after the date and time.
|
|
* @return A string representing the generated WAV file name.
|
|
*/
|
|
fun Make_WAV_FileName(prefix: String, postfix: String) : String{
|
|
val sb = StringBuilder()
|
|
if (prefix.isNotEmpty()){sb.append(prefix).append("_")}
|
|
sb.append(filenameformat.format(LocalDateTime.now()))
|
|
if (postfix.isNotEmpty()){sb.append("_").append(postfix)}
|
|
sb.append(".wav")
|
|
return sb.toString()
|
|
}
|
|
}
|
|
|
|
|
|
} |