1
0

feat: 完成优化器设计

This commit is contained in:
2024-12-23 15:05:42 +08:00
parent 7676f8c890
commit 3c6369b07d
7 changed files with 347 additions and 130 deletions

View File

@@ -5,6 +5,14 @@ data class PageResponse<E>(
val total: Long, val total: Long,
) )
data class MapResponse(
val data: Map<String, Any>,
)
data class ListResponse(
val data: List<Any>
)
data class SingleResponse<E>( data class SingleResponse<E>(
val data: Map<String, E>, val data: Map<String, E>,
) { ) {

View File

@@ -0,0 +1,103 @@
package com.lanyuanxiaoyao.bookstore
import cn.hutool.core.convert.Convert
import com.fasterxml.jackson.databind.JsonNode
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.LIST
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.MAP
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.NONE
// @Configuration
// class ProcessorConfiguration {
// @Bean
// fun processors(): Map<String, Processor> = listOf(
// CharWidthProcessor()
// ).associateBy { it.javaClass.name }
// }
interface Optimization {
companion object {
fun process(root: JsonNode, optimizationMap: Map<String, Optimization>): List<String> {
val text = root.get("text").asText()
val nodes = root.get("optimizations") ?: emptyList()
var lines = listOf(text)
for (node in nodes) {
val type = node.get("type").asText()
val optimization = optimizationMap[type] ?: throw IllegalArgumentException("Unknown optimization type: $type")
lines = when (optimization.argumentType()) {
NONE -> optimization.handle(lines, Unit)
LIST -> optimization.handle(lines, node.get("argument").map { it.asText() })
MAP -> optimization.handle(lines,
node
.get("argument")
.fields()
.asSequence()
.map { (k, v) -> k to v.asText() }
.toMap()
)
}
}
return lines
}
}
enum class ArgumentType {
NONE, LIST, MAP
}
fun key(): String
fun name(): String
fun handle(line: List<String>, argument: Any): List<String>
fun argumentType(): ArgumentType
}
class SliceOptimization() : Optimization {
override fun key(): String = "slice-${argumentType()}"
override fun name(): String = "切分"
override fun handle(line: List<String>, argument: Any): List<String> {
val keys = argument as List<String>
var result = line
for (key in keys) {
result = result.flatMap { it.split(key) }
}
return result
}
override fun argumentType(): Optimization.ArgumentType = Optimization.ArgumentType.LIST
}
abstract class AbstractOptimization(private val key: String, private val name: String) : Optimization {
override fun key(): String = "${key}-${argumentType()}"
override fun name(): String = name
override fun handle(line: List<String>, argument: Any): List<String> {
return line.map { handle(it, argument) }
}
override fun argumentType(): Optimization.ArgumentType = Optimization.ArgumentType.NONE
abstract fun handle(line: String, argument: Any): String
}
class TrimOptimization : AbstractOptimization("trim", "移除前后空白") {
override fun handle(line: String, argument: Any): String {
if (line.isBlank()) return line
return line.trim()
}
}
class CharWidthOptimization : AbstractOptimization("char-width", "半角字符转全角字符") {
override fun handle(line: String, argument: Any): String {
if (line.isBlank()) return line
return Convert
.toDBC(line)
.replace(",", "")
.replace("?", "")
.replace("!", "")
.replace(";", "")
.replace(":", "")
.replace("(", "")
.replace(")", "")
}
}

View File

@@ -1,52 +0,0 @@
package com.lanyuanxiaoyao.bookstore
import cn.hutool.core.convert.Convert
// @Configuration
// class ProcessorConfiguration {
// @Bean
// fun processors(): Map<String, Processor> = listOf(
// CharWidthProcessor()
// ).associateBy { it.javaClass.name }
// }
interface Slicer {
fun slice(text: String): List<String>
}
open class RegexSlicer(private val regex: Regex) : Slicer {
override fun slice(text: String): List<String> {
return text.split(regex)
}
}
interface Optimization {
fun handle(line: String): String
}
class TrimOptimization : Optimization {
override fun handle(line: String): String {
if (line.isBlank()) return line
return line.trim()
}
}
class CharWidthOptimization : Optimization {
override fun handle(line: String): String {
if (line.isBlank()) return line
return Convert.toDBC(line)
}
}
class QuoteCovertChineseOptimization : Optimization {
override fun handle(line: String): String {
return line
.replace(",", "")
.replace("?", "")
.replace("!", "")
.replace(";", "")
.replace(":", "")
.replace("(", "")
.replace(")", "")
}
}

View File

@@ -0,0 +1,46 @@
package com.lanyuanxiaoyao.bookstore.controller
import com.fasterxml.jackson.databind.ObjectMapper
import com.lanyuanxiaoyao.bookstore.CharWidthOptimization
import com.lanyuanxiaoyao.bookstore.ListResponse
import com.lanyuanxiaoyao.bookstore.Optimization
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.LIST
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.MAP
import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.NONE
import com.lanyuanxiaoyao.bookstore.SingleResponse
import com.lanyuanxiaoyao.bookstore.SliceOptimization
import com.lanyuanxiaoyao.bookstore.TrimOptimization
import java.awt.SystemColor.text
import org.slf4j.LoggerFactory
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("optimization")
class OptimizationController(builder: Jackson2ObjectMapperBuilder) {
private val log = LoggerFactory.getLogger(javaClass)
private val mapper: ObjectMapper = builder.build()
private val optimizations: List<Optimization> = listOf(
SliceOptimization(),
TrimOptimization(),
CharWidthOptimization(),
)
private val optimizationMap: Map<String, Optimization> = optimizations.associateBy { it.key() }
@GetMapping("optimizations")
fun optimizations(): ListResponse {
return ListResponse(optimizations.map { mapOf("value" to it.key(), "label" to it.name()) })
}
@PostMapping("execute")
fun execute(@RequestBody json: String): SingleResponse<String> {
val root = mapper.readTree(json)
val lines = Optimization.process(root, optimizationMap)
return SingleResponse(lines.joinToString("\n"))
}
}

View File

@@ -36,3 +36,11 @@ function paginationOption() {
total: '${total}' total: '${total}'
} }
} }
function arrayInCheck(array, field) {
return `\${ARRAYINCLUDES(['${array.join("','")}'], ${field})}`
}
function arrayOutCheck(array, field) {
return `\${!ARRAYINCLUDES(['${array.join("','")}'], ${field})}`
}

View File

@@ -27,17 +27,29 @@
<div id="root"></div> <div id="root"></div>
</body> </body>
<script src="sdk/sdk.js"></script> <script src="sdk/sdk.js"></script>
<script>
const information = {
debug: false,
name: '书籍中心',
description: '网络书籍精排版工具',
base: 'http://127.0.0.1:23890',
}
</script>
<script src="components/helper.js"></script> <script src="components/helper.js"></script>
<script src="components/book.js"></script> <script src="components/book.js"></script>
<script src="components/chapter.js"></script> <script src="components/chapter.js"></script>
<script> <script>
(function () { (function () {
let debug = false
let amis = amisRequire('amis/embed') let amis = amisRequire('amis/embed')
let amisJSON = { let amisJSON = {
type: 'page', type: 'page',
title: '书籍中心', title: '书籍中心',
subTitle: '网络书籍精排版工具', subTitle: '网络书籍精排版工具',
body: {
type: 'tabs',
tabs: [
{
title: '书架',
body: [ body: [
{ {
id: 'book-list', id: 'book-list',
@@ -110,22 +122,115 @@
}, },
], ],
}, },
], ]
},
{
title: '优化',
body: [
{
type: 'form',
name: 'optimization-form',
body: [
{
type: 'textarea',
name: 'text',
label: '正文',
required: true,
...formInputClearable(),
showCounter: true,
trimContents: true,
minRows: 5,
maxRows: 5,
},
{
type: 'combo',
name: 'optimizations',
label: '优化器',
required: true,
multiLine: true,
multiple: true,
draggable: true,
items: [
{
name: 'type',
label: '类型',
type: 'select',
required: true,
selectFirst: true,
source: '${base}/optimization/optimizations',
},
{
visibleOn: "${ENDSWITH(type, 'MAP')}",
type: 'input-kv',
name: 'argument',
label: '参数',
required: true,
},
{
visibleOn: "${ENDSWITH(type, 'LIST')}",
type: 'combo',
name: 'argument',
label: '参数',
required: true,
multiple: true,
multiLine: true,
flat: true,
items: [
{
type: 'input-text',
name: 'argument',
label: '目标值',
required: true,
}
]
},
]
},
{
type: 'action',
label: '执行优化',
className: 'w-full mb-5',
level: 'primary',
actionType: 'ajax',
api: {
method: 'post',
url: '${base}/optimization/execute',
data: {
text: '${text|default:undefined}',
optimizations: '${optimizations|default:undefined}'
}
},
reload: 'optimization-form?newText=${item}'
},
{
disabled: true,
type: 'diff-editor',
name: 'newText',
label: '正文优化',
diffValue: '${text}',
language: 'plain-text'
},
]
},
]
}
]
},
} }
amis.embed( amis.embed(
'#root', '#root',
amisJSON, amisJSON,
{ {
data: { data: {
base: 'http://127.0.0.1:23890', ...information
}, },
}, },
{ {
theme: 'antd', theme: 'antd',
enableAMISDebug: debug, enableAMISDebug: information.debug,
}, },
); );
if (debug) { if (information.debug) {
console.log('Source', amisJSON) console.log('Source', amisJSON)
} }
})() })()

View File

@@ -9,11 +9,10 @@ class ChapterOptimization {
val optimizations = listOf( val optimizations = listOf(
TrimOptimization(), TrimOptimization(),
CharWidthOptimization(), CharWidthOptimization(),
QuoteCovertChineseOptimization(),
) )
val content = File("C:\\Users\\lanyuanxiaoyao\\Downloads\\第141章-反攻云岚宗.txt") val content = File("C:\\Users\\lanyuanxiaoyao\\Downloads\\第141章-反攻云岚宗.txt")
.readLines() .readLines()
.joinToString("\n") { optimizations.fold(it) { line, optimization -> optimization.handle(line) } } .joinToString("\n") { optimizations.fold(it) { line, optimization -> optimization.handle(line, optimization.argumentType()) } }
println(content) println(content)
} }
} }