feat: 完成优化器设计
This commit is contained in:
@@ -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>,
|
||||||
) {
|
) {
|
||||||
|
|||||||
103
src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt
Normal file
103
src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt
Normal 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(")", ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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(")", ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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})}`
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,105 +27,210 @@
|
|||||||
<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: [
|
body: {
|
||||||
{
|
type: 'tabs',
|
||||||
id: 'book-list',
|
tabs: [
|
||||||
type: 'crud',
|
{
|
||||||
api: {
|
title: '书架',
|
||||||
method: 'get',
|
body: [
|
||||||
url: '${base}/book/list',
|
{
|
||||||
data: {
|
id: 'book-list',
|
||||||
page: '${page|default:1}',
|
type: 'crud',
|
||||||
size: '${size|default:10}'
|
api: {
|
||||||
}
|
method: 'get',
|
||||||
|
url: '${base}/book/list',
|
||||||
|
data: {
|
||||||
|
page: '${page|default:1}',
|
||||||
|
size: '${size|default:10}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...crudCommonOptions(),
|
||||||
|
headerToolbar: [
|
||||||
|
'reload',
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
icon: 'fa fa-add',
|
||||||
|
...bookAddDialog(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
footerToolbar: [
|
||||||
|
paginationOption(),
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: '名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
fixed: 'right',
|
||||||
|
className: 'nowrap',
|
||||||
|
width: 100,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '跳转',
|
||||||
|
actionType: 'url',
|
||||||
|
url: '${source}',
|
||||||
|
blank: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '导出',
|
||||||
|
actionType: 'download',
|
||||||
|
api: '${base}/book/export/${bookId}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '编辑',
|
||||||
|
...bookDetailDialog(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '删除',
|
||||||
|
level: 'danger',
|
||||||
|
confirmTitle: '确认删除',
|
||||||
|
confirmText: '确认删除名称为「${name}」的书籍吗?',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: 'get:${base}/book/remove/${bookId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
...crudCommonOptions(),
|
{
|
||||||
headerToolbar: [
|
title: '优化',
|
||||||
'reload',
|
body: [
|
||||||
{
|
{
|
||||||
label: '',
|
type: 'form',
|
||||||
icon: 'fa fa-add',
|
name: 'optimization-form',
|
||||||
...bookAddDialog(),
|
body: [
|
||||||
},
|
{
|
||||||
],
|
type: 'textarea',
|
||||||
footerToolbar: [
|
name: 'text',
|
||||||
paginationOption(),
|
label: '正文',
|
||||||
],
|
required: true,
|
||||||
columns: [
|
...formInputClearable(),
|
||||||
{
|
showCounter: true,
|
||||||
name: 'name',
|
trimContents: true,
|
||||||
label: '名称',
|
minRows: 5,
|
||||||
width: 150,
|
maxRows: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'description',
|
type: 'combo',
|
||||||
label: '描述',
|
name: 'optimizations',
|
||||||
},
|
label: '优化器',
|
||||||
{
|
required: true,
|
||||||
type: 'operation',
|
multiLine: true,
|
||||||
label: '操作',
|
multiple: true,
|
||||||
fixed: 'right',
|
draggable: true,
|
||||||
className: 'nowrap',
|
items: [
|
||||||
width: 100,
|
{
|
||||||
buttons: [
|
name: 'type',
|
||||||
{
|
label: '类型',
|
||||||
type: 'action',
|
type: 'select',
|
||||||
label: '跳转',
|
required: true,
|
||||||
actionType: 'url',
|
selectFirst: true,
|
||||||
url: '${source}',
|
source: '${base}/optimization/optimizations',
|
||||||
blank: true,
|
},
|
||||||
},
|
{
|
||||||
{
|
visibleOn: "${ENDSWITH(type, 'MAP')}",
|
||||||
type: 'action',
|
type: 'input-kv',
|
||||||
label: '导出',
|
name: 'argument',
|
||||||
actionType: 'download',
|
label: '参数',
|
||||||
api: '${base}/book/export/${bookId}',
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'action',
|
visibleOn: "${ENDSWITH(type, 'LIST')}",
|
||||||
label: '编辑',
|
type: 'combo',
|
||||||
...bookDetailDialog(),
|
name: 'argument',
|
||||||
},
|
label: '参数',
|
||||||
{
|
required: true,
|
||||||
type: 'action',
|
multiple: true,
|
||||||
label: '删除',
|
multiLine: true,
|
||||||
level: 'danger',
|
flat: true,
|
||||||
confirmTitle: '确认删除',
|
items: [
|
||||||
confirmText: '确认删除名称为「${name}」的书籍吗?',
|
{
|
||||||
actionType: 'ajax',
|
type: 'input-text',
|
||||||
api: 'get:${base}/book/remove/${bookId}',
|
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)
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user