@@ -40,6 +40,7 @@ import com.halilibo.richtext.ui.RichTextStyle
4040import com.movtery.zalithlauncher.ui.components.MarkdownView
4141import com.movtery.zalithlauncher.ui.components.defaultRichTextStyle
4242import com.movtery.zalithlauncher.ui.theme.itemColor
43+ import kotlin.random.Random
4344
4445fun LazyListScope.customHomePage (
4546 blocks : List <MarkdownBlock >,
@@ -399,17 +400,19 @@ private fun parseMarkdownBlocksInternal(
399400 if (match == null ) {
400401 // 没有更多匹配,添加剩余内容
401402 val remaining = cleared.substring(lastIndex).trim(' \n ' )
402- if (remaining.isNotEmpty()) {
403- blocks.add(MarkdownBlock .Normal (astNode = parseMarkdown(remaining)))
403+ val processedRemaining = processRandomBlocksInText(remaining)
404+ if (processedRemaining.isNotEmpty()) {
405+ blocks.add(MarkdownBlock .Normal (astNode = parseMarkdown(processedRemaining)))
404406 }
405407 break
406408 }
407409
408410 // 处理匹配项之前的普通文本
409411 if (match.range.first > lastIndex) {
410412 val text = cleared.substring(lastIndex, match.range.first).trim(' \n ' )
411- if (text.isNotEmpty()) {
412- blocks.add(MarkdownBlock .Normal (astNode = parseMarkdown(text)))
413+ val processedText = processRandomBlocksInText(text)
414+ if (processedText.isNotEmpty()) {
415+ blocks.add(MarkdownBlock .Normal (astNode = parseMarkdown(processedText)))
413416 }
414417 }
415418
@@ -793,4 +796,101 @@ private fun parseWeight(params: String): Pair<Float, Boolean>? {
793796 val weight = match.groupValues[1 ].toFloatOrNull() ? : return null
794797 val fill = match.groupValues[2 ] != " noFill"
795798 return Pair (weight, fill)
799+ }
800+
801+ private const val randomStartTag = " ...random-start"
802+ private const val randomEndTag = " ...random-end"
803+ private val randomOptionRegex = Regex (""" ^weight\((\d+(?:\.\d+)?)\)\s*:\s*(.*)$""" )
804+
805+ private data class RandomOption (
806+ val text : String ,
807+ val weight : Double
808+ )
809+
810+ /* *
811+ * 处理文本中的随机文本块,自动将其替换为随机选中的文本
812+ * 语法:
813+ * ```
814+ * ...random-start
815+ * weight(N): 文本内容
816+ * 默认权重的文本内容
817+ * ...random-end
818+ * ```
819+ * - 以 `weight(N): ` 开头可指定权重,否则权重默认为 1
820+ * - 随机抽取后的结果中不包含换行符
821+ */
822+ private fun processRandomBlocksInText (text : String ): String {
823+ if (! text.contains(randomStartTag)) return text
824+
825+ val lines = text.lines()
826+ val result = mutableListOf<String >()
827+ var inRandomBlock = false
828+ var randomStartLine: String? = null
829+ val randomLines = mutableListOf<String >()
830+
831+ for (line in lines) {
832+ val trimmed = line.trimStart()
833+
834+ if (inRandomBlock) {
835+ if (trimmed.startsWith(randomEndTag)) {
836+ val selected = pickRandomText(randomLines)
837+ result.add(selected)
838+ randomLines.clear()
839+ inRandomBlock = false
840+ randomStartLine = null
841+ } else {
842+ randomLines.add(line)
843+ }
844+ } else {
845+ if (trimmed.startsWith(randomStartTag)) {
846+ inRandomBlock = true
847+ randomStartLine = line
848+ } else {
849+ result.add(line)
850+ }
851+ }
852+ }
853+
854+ // 如果文本结束但随机块未闭合,则忽略此随机文本块
855+ if (inRandomBlock) {
856+ randomStartLine?.let { result.add(it) }
857+ result.addAll(randomLines)
858+ }
859+
860+ return result.joinToString(" \n " )
861+ }
862+
863+ /* *
864+ * 从随机文本候选项中根据权重抽取一个文本
865+ */
866+ private fun pickRandomText (lines : List <String >): String {
867+ val options = lines.mapNotNull { line ->
868+ val trimmed = line.trim()
869+ if (trimmed.isEmpty()) return @mapNotNull null
870+
871+ // 读取权重值
872+ val match = randomOptionRegex.find(trimmed)
873+ if (match != null ) {
874+ val weight = match.groupValues[1 ].toDoubleOrNull() ? : 1.0
875+ val text = match.groupValues[2 ]
876+ RandomOption (text, weight)
877+ } else {
878+ // 未配置权重时,默认为 1
879+ RandomOption (trimmed, 1.0 )
880+ }
881+ }
882+
883+ if (options.isEmpty()) return " "
884+
885+ val totalWeight = options.sumOf { it.weight }
886+ var randomValue = Random .nextDouble() * totalWeight
887+
888+ for (option in options) {
889+ randomValue - = option.weight
890+ if (randomValue <= 0 ) {
891+ return option.text
892+ }
893+ }
894+
895+ return options.last().text
796896}
0 commit comments