Skip to content

Commit 35d2cb3

Browse files
add sorting and column types
1 parent b796220 commit 35d2cb3

File tree

3 files changed

+90
-56
lines changed

3 files changed

+90
-56
lines changed

src/main/kotlin/com/bitkid/itsfranking/ITSFRankingApp.kt

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -38,52 +38,64 @@ object ITSFRankingApp {
3838

3939
val version = getVersionFromJarFile()
4040

41-
4241
private val playerNameField = JTextField(50)
4342
private val itsfNoField = JTextField(50)
4443

45-
private val jTable = JTable(emptyModel()).apply {
44+
private val searchResultTable = JTable(emptySearchResultModel()).apply {
4645
cellSelectionEnabled = true
46+
autoCreateRowSorter = true
4747
}
4848

49-
private val jTableList = JTable(emptyListResultModelSingles()).apply {
49+
private val csvListTable = JTable(emptyCsvListModelSingles()).apply {
5050
cellSelectionEnabled = true
51+
autoCreateRowSorter = true
5152
}
5253

53-
private val jTableRanking = JTable(emptyRankingModel()).apply {
54+
private val rankingTable = JTable(emptyRankingModel()).apply {
5455
cellSelectionEnabled = true
56+
autoCreateRowSorter = true
5557
}
5658

5759
private val tabbedPane = JTabbedPane()
58-
59-
60-
private fun emptyModel() = ResultTableModel(listOf("itsf no.", "name", "country") + Categories.all.map { it.targetAudience })
61-
62-
private fun emptyRankingModel() = ResultTableModel(listOf("itsf no.", "name", "country", "rank", "points"))
63-
64-
private fun emptyListResultModelSingles() = ResultTableModel(listOf("player", "itsf name", "country", "points", "rank", "status"), true)
65-
private fun emptyListResultModelDoubles() =
66-
ResultTableModel(
67-
listOf("player1", "itsf name 1", "player2", "itsf name 2", "combined", "p1 country", "p1 points", "p1 rank", "p1 status", "p2 country", "p2 points", "p2 rank", "p2 status"),
68-
true
60+
private fun emptySearchResultModel() = ResultTableModel(listOf("itsf no.", "name", "country") + Categories.all.map { it.targetAudience })
61+
private fun emptyRankingModel() = ResultTableModel(listOf("rank", "name", "country", "itsf no.", "points"))
62+
private fun emptyCsvListModelSingles() = ResultTableModel(listOf("player", "itsf name", "country", "points", "rank", "status"), true)
63+
private fun emptyCsvListModelDoubles() = DoublesListModel(
64+
listOf(
65+
"player1",
66+
"itsf name 1",
67+
"player2",
68+
"itsf name 2",
69+
"combined",
70+
"p1 country",
71+
"p1 points",
72+
"p1 rank",
73+
"p1 status",
74+
"p2 country",
75+
"p2 points",
76+
"p2 rank",
77+
"p2 status"
6978
)
79+
)
7080

7181
private fun showRanking(category: String) {
72-
if (checkRankingLoaded()) {
82+
if (checkITSFDataLoaded()) {
7383
val cat = Categories.all.single { it.targetAudience == category }
7484
val players = itsfPlayers.getSortedRanking(cat)
7585
val m = emptyRankingModel()
7686
players.forEach {
7787
val itsfRank = it.rankings.getValue(cat)
78-
val props = listOf(it.licenseNumber, it.name, it.country, itsfRank.rank.toString(), itsfRank.points.toString())
88+
listOf("rank", "name", "country", "itsf no.", "points")
89+
val props = listOf(itsfRank.rank, it.name, it.country, it.licenseNumber, itsfRank.points)
7990
m.addRow(props)
8091
}
81-
jTableRanking.model = m
92+
rankingTable.rowSorter = null
93+
rankingTable.model = m
8294
tabbedPane.selectedIndex = 2
8395
}
8496
}
8597

86-
private fun checkRankingLoaded(): Boolean {
98+
private fun checkITSFDataLoaded(): Boolean {
8799
if (!this::itsfPlayers.isInitialized) {
88100
JOptionPane.showMessageDialog(jFrame, "Load rankings first!", "Info", JOptionPane.INFORMATION_MESSAGE)
89101
return false
@@ -92,61 +104,62 @@ object ITSFRankingApp {
92104
}
93105

94106
private fun modelWithPlayers(players: Collection<ITSFPlayer>): ResultTableModel {
95-
val model = emptyModel()
96-
players.forEach { addPlayerToModel(model, it) }
107+
val model = emptySearchResultModel()
108+
players.forEach { addPlayerToSearchResultModel(model, it) }
97109
return model
98110
}
99111

100-
private suspend fun loadRanking(s: String) {
112+
private suspend fun loadITSFDATA(s: String) {
101113
// val rankings = ITSFPlayerDatabaseReader(topXPlayers = 2000).readTestRankings()
102114
val rankings = ITSFPlayerDatabaseReader(topXPlayers = 2000, tour = s).readRankings()
103115
itsfPlayers = ITSFPlayers(rankings)
104116
}
105117

106-
private fun searchLicenseNumber() {
107-
if (checkRankingLoaded()) {
118+
private fun searchForLicenseNumber() {
119+
if (checkITSFDataLoaded()) {
108120
val text = itsfNoField.text
109121
if (!text.isNullOrBlank()) {
110122
val player = itsfPlayers.getPlayer(text)
123+
searchResultTable.rowSorter = null
111124
if (player == null)
112-
jTable.model = emptyModel()
125+
searchResultTable.model = emptySearchResultModel()
113126
else
114-
jTable.model = modelWithPlayers(listOf(player))
127+
searchResultTable.model = modelWithPlayers(listOf(player))
115128
tabbedPane.selectedIndex = 0
116129
}
117130
}
118131
}
119132

120-
private fun searchByName() {
121-
if (checkRankingLoaded()) {
133+
private fun searchForName() {
134+
if (checkITSFDataLoaded()) {
122135
val text = playerNameField.text
123136
if (!text.isNullOrBlank()) {
124137
val player = itsfPlayers.find(text, true)
125-
jTable.model = modelWithPlayers(player)
138+
searchResultTable.rowSorter = null
139+
searchResultTable.model = modelWithPlayers(player)
126140
tabbedPane.selectedIndex = 0
127141
}
128142
}
129143
}
130144

131145

132-
private fun loadFile(file: File, charset: Charset, category: Category) {
146+
private fun loadCsvFile(file: File, charset: Charset, category: Category) {
133147
val listMatcher = ListMatcher(itsfPlayers)
134148
val model = if (category.type == CompetitionType.SINGLES) {
135-
val model = emptyListResultModelSingles()
149+
val model = emptyCsvListModelSingles()
136150
listMatcher.matchPlayer(file, charset, category).forEach {
137151
when (it.results.size) {
138152
0 -> model.addRow(listOf(it.playerName, null, null, null, null, "NOT_FOUND"))
139153
1 -> {
140154
val player = it.results.single()
141155
model.addRow(listOf(it.playerName, player.name, player.country, player.rankings[category]?.points ?: 0, player.rankings[category]?.rank, "OK"))
142156
}
143-
144157
else -> model.addRow(listOf(it.playerName, null, null, null, null, "MULTIPLE_MATCHES"))
145158
}
146159
}
147160
model
148161
} else {
149-
val model = emptyListResultModelDoubles()
162+
val model = emptyCsvListModelDoubles()
150163
listMatcher.matchTeam(file, charset, category).forEach { pwr ->
151164
val list = mutableListOf<Any?>(pwr.player1.playerName, pwr.player2.playerName)
152165
val p1 = addPlayerToRow(list, category, pwr.player1)
@@ -160,7 +173,8 @@ object ITSFRankingApp {
160173
}
161174
model
162175
}
163-
jTableList.model = model
176+
csvListTable.rowSorter = null
177+
csvListTable.model = model
164178
tabbedPane.selectedIndex = 1
165179
}
166180

@@ -170,21 +184,19 @@ object ITSFRankingApp {
170184
list.addAll(listOf(null, null, null, "NOT_FOUND"))
171185
null
172186
}
173-
174187
1 -> {
175188
val player = playerNameWithResults.results.single()
176189
list.addAll(listOf(player.country, player.rankings[category]?.points ?: 0, player.rankings[category]?.rank, "OK"))
177190
player
178191
}
179-
180192
else -> {
181193
list.addAll(listOf(null, null, null, "MULTIPLE_MATCHES"))
182194
null
183195
}
184196
}
185197
}
186198

187-
private fun addPlayerToModel(model: ResultTableModel, it: ITSFPlayer) {
199+
private fun addPlayerToSearchResultModel(model: ResultTableModel, it: ITSFPlayer) {
188200
val ranks = Categories.all.map { c ->
189201
val r = it.rankings[c]
190202
if (r == null)
@@ -197,22 +209,22 @@ object ITSFRankingApp {
197209
}
198210

199211

200-
private fun createPanel(frame: JFrame): JPanel {
212+
private fun createMainPanel(frame: JFrame): JPanel {
201213
jFrame = frame
202214
val panel = JPanel(MigLayout("wrap 2"))
203215

204216
panel.add(JLabel("Load ITSF Rankings"))
205-
panel.add(LoadITSFDataPanel { loadRanking(it) }, "growx")
217+
panel.add(LoadITSFDataPanel { loadITSFDATA(it) }, "growx")
206218

207219
val searchAction: Action = object : AbstractAction() {
208220
override fun actionPerformed(e: ActionEvent) {
209-
searchByName()
221+
searchForName()
210222
}
211223
}
212224

213225
val searchLicenseAction: Action = object : AbstractAction() {
214226
override fun actionPerformed(e: ActionEvent) {
215-
searchLicenseNumber()
227+
searchForLicenseNumber()
216228
}
217229
}
218230

@@ -232,13 +244,13 @@ object ITSFRankingApp {
232244
panel.add(JButton("Search").apply { addActionListener(searchLicenseAction) }, "growx")
233245

234246
panel.add(JLabel("Upload player list"))
235-
panel.add(LoadCsvPanel(::loadFile, ::checkRankingLoaded), "growx")
247+
panel.add(LoadCsvPanel(::loadCsvFile, ::checkITSFDataLoaded), "growx")
236248

237-
panel.add(JLabel("Results"))
249+
panel.add(JLabel("Data"))
238250

239-
tabbedPane.addTab("Search results", JScrollPane(jTable))
240-
tabbedPane.addTab("Player list", JScrollPane(jTableList))
241-
tabbedPane.addTab("Rankings", JScrollPane(jTableRanking))
251+
tabbedPane.addTab("Search results", JScrollPane(searchResultTable))
252+
tabbedPane.addTab("Player list", JScrollPane(csvListTable))
253+
tabbedPane.addTab("Rankings", JScrollPane(rankingTable))
242254
panel.add(tabbedPane, "growx, height :400:")
243255

244256
return panel
@@ -253,7 +265,7 @@ object ITSFRankingApp {
253265
ex.printStackTrace()
254266
}
255267
val frame = JFrame("ITSF Rankings ($version)")
256-
frame.contentPane.add(createPanel(frame))
268+
frame.contentPane.add(createMainPanel(frame))
257269
frame.pack()
258270
frame.isResizable = false
259271
frame.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE

src/main/kotlin/com/bitkid/itsfranking/ui/LoadCsvPanel.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import com.bitkid.itsfranking.Categories
44
import com.bitkid.itsfranking.Category
55
import com.bitkid.itsfranking.ITSFRankingApp
66
import com.bitkid.itsfranking.showLoadingDialog
7-
import kotlinx.coroutines.DelicateCoroutinesApi
8-
import kotlinx.coroutines.Dispatchers
9-
import kotlinx.coroutines.GlobalScope
10-
import kotlinx.coroutines.launch
7+
import kotlinx.coroutines.*
8+
import kotlinx.coroutines.swing.Swing
119
import net.miginfocom.swing.MigLayout
1210
import java.io.File
1311
import java.nio.charset.Charset
@@ -34,11 +32,18 @@ class LoadCsvPanel(private val load: (File, Charset, Category) -> Unit, private
3432
val r = fileChooser.showOpenDialog(ITSFRankingApp.jFrame)
3533
if (r == JFileChooser.APPROVE_OPTION) {
3634
val dialog = showLoadingDialog()
37-
currentDirectory = fileChooser.selectedFile.parentFile
38-
GlobalScope.launch(Dispatchers.IO) {
35+
val currentFile = fileChooser.selectedFile
36+
currentDirectory = currentFile.parentFile
37+
val job = GlobalScope.async(Dispatchers.IO) {
38+
load(
39+
currentFile,
40+
Charset.forName(charsetSelect.selectedItem!!.toString()),
41+
Categories.all.single { it.name == category.selectedItem!! }
42+
)
43+
}
44+
GlobalScope.launch(Dispatchers.Swing) {
3945
try {
40-
val file = fileChooser.selectedFile
41-
load(file, Charset.forName(charsetSelect.selectedItem!!.toString()), Categories.all.single { it.name == category.selectedItem!! })
46+
job.await()
4247
} catch (e: Exception) {
4348
dialog.dispose()
4449
JOptionPane.showMessageDialog(

src/main/kotlin/com/bitkid/itsfranking/ui/ResultTableModel.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,27 @@ package com.bitkid.itsfranking.ui
33
import java.util.*
44
import javax.swing.table.DefaultTableModel
55

6-
class ResultTableModel(columns: List<String>, private val editable: Boolean = false) : DefaultTableModel(Vector(columns), 0) {
6+
open class ResultTableModel(columns: List<String>, private val editable: Boolean = false) : DefaultTableModel(Vector(columns), 0) {
77
override fun isCellEditable(row: Int, column: Int): Boolean {
88
return editable
99
}
10+
11+
override fun getColumnClass(c: Int): Class<*> {
12+
val javaClass = getValueAt(0, c).javaClass
13+
return javaClass
14+
}
15+
}
16+
17+
class DoublesListModel(columns: List<String>) : ResultTableModel(columns, true) {
18+
override fun setValueAt(aValue: Any?, row: Int, column: Int) {
19+
super.setValueAt(aValue, row, column)
20+
val current = (aValue as? Int) ?: 0
21+
if (column == 6) {
22+
super.setValueAt(((getValueAt(row, 10) as? Int) ?: 0) + current, row, 4)
23+
} else if (column == 10) {
24+
super.setValueAt(((getValueAt(row, 6) as? Int) ?: 0) + current, row, 4)
25+
}
26+
}
1027
}
1128

1229
fun ResultTableModel.addRow(data: List<*>) {

0 commit comments

Comments
 (0)