Module:时间线

Template-info.svg 模块文档  [创建] [刷新]
  1. local module = {}
  2. local getArgs = require('Module:Arguments').getArgs
  3. --定义每次开头都是时间段而不是时间点
  4. --辅助处理trim
  5. function module.trim_step(text,patterns)
  6. for _,pattern in ipairs(patterns) do
  7. local b,e=text:find(pattern)
  8. if b then
  9. return true,string.sub(text,e+1)
  10. end
  11. end
  12. return false,text
  13. end
  14. function module.trim(text,patterns)
  15. local bool=true
  16. while bool do
  17. bool,text=module.trim_step(text,patterns)
  18. end
  19. return text
  20. end
  21. function module.trimCount(text,patterns)
  22. local bool=true
  23. local count=-1
  24. while bool do
  25. bool,text=module.trim_step(text,patterns)
  26. count=count+1
  27. end
  28. return text,count
  29. end
  30. --时间线/事件元表
  31. local timeLine={format={},analysis={}}
  32. function timeLine:timeSupply()--补足省略前缀时间
  33. if self.time~=nil then
  34. if timeLine.lastLine~=nil then
  35. --mw.log("time",self.time,self.time:getNumber())
  36. --mw.log("timeUse",timeLine.lastLine.time,timeLine.lastLine.time:getNumber())
  37. self.time:supply(timeLine.lastLine.time,true,false)
  38. --mw.log("totime",self.time,self.time:getNumber())
  39. --mw.log(self.time,self.time:compare(timeLine.lastLine.time),timeLine.lastLine.time)
  40. end
  41. elseif timeLine.lastLine then
  42. self.time=mw.clone(timeLine.lastLine.time)
  43. --mw.log(tostring(defaultTime).."--same--"..tostring(this))
  44. end
  45. end
  46. function timeLine.appendText(text)--为最后创建的timeLine追加文本
  47. if timeLine.lastLine then
  48. if timeLine.lastLine.text then
  49. timeLine.lastLine.text=timeLine.lastLine.text..timeLine.format.split..text
  50. else
  51. timeLine.lastLine.text=text
  52. end
  53. end
  54. return timeLine.lastLine
  55. end
  56. function timeLine.base(args)
  57. return setmetatable(args or {},timeLine)
  58. end
  59. timeLine.__index = timeLine
  60. function timeLine.title(titleLevel)
  61. assert(titleLevel,"标题层级不能为nil")
  62. return timeLine.base{titleLevel=titleLevel}
  63. end
  64. function timeLine.root()
  65. return timeLine.title(0)
  66. end
  67. function timeLine.create(withTimeText,parent)--带时间文本时间数字化·文本化函数
  68. assert(withTimeText~=nil and withTimeText~="","被分析文本不能为空")
  69. local titleLevel
  70. withTimeText,titleLevel=module.trimCount(withTimeText,timeLine.analysis.title)
  71. withTimeText=module.trim(withTimeText,timeLine.analysis.trim)
  72. withTimeText=module.trim(withTimeText,timeLine.analysis.sameTimeTable)
  73. local time,index=timeLine.getTime(withTimeText)
  74. if index==1 then
  75. time=nil
  76. end
  77. local text=module.trim(withTimeText:sub(index),timeLine.analysis.timeTextSplit)
  78. if #text+titleLevel==#withTimeText then--这是一行不具有时间效用的文本,实质为上一行文本的扩展部分。
  79. return timeLine.appendText(text)
  80. end
  81. local line=timeLine.base{time=time,text=text,titleLevel=titleLevel>0 and titleLevel}
  82. line:timeSupply()
  83. if parent then
  84. parent:insert(line)
  85. end
  86. timeLine.lastLine=line
  87. return line
  88. end
  89. function timeLine.titleMake(fulltime,level)--制作标题
  90. time=mw.clone(fulltime)
  91. --mw.log("->",timeLine.format.titleUnitList[level+timeLine.format.titleUnit-1],time)
  92. time:coverUnit(timeLine.format.titleUnitList[level+timeLine.format.titleUnit-1],true)
  93. if time:isEmpty() or time==fulltime then--没有可拆分信息
  94. return nil
  95. end
  96. local tag,range=time.accuracy:getMin()
  97. --mw.log(tag,range)
  98. local line=timeLine.title(timeLine.format.titleTopLevel+level-1)
  99. line.time=time
  100. return line
  101. end
  102. function timeLine:_insertTitile(newLine,index)--实际插入函数
  103. --mw.log("insert",self:currentlevel(),timeLine.format.titleLevel,self.titleLevel)
  104. if self.titleLevel and self:currentlevel()<timeLine.format.titleLevel then
  105. --mw.log("make",self:currentlevel()+1)
  106. local tl=timeLine.titleMake(newLine.time,self:currentlevel()+1)
  107. if not tl then--变成标题
  108. newLine.titleLevel=timeLine.format.titleTopLevel+self:currentlevel()
  109. newLine.parent=self
  110. table.insert(self,index,newLine)
  111. else
  112. tl.parent=self
  113. table.insert(self,index,tl)
  114. tl:_insertTitile(newLine,1)
  115. end
  116. else
  117. newLine.parent=self
  118. table.insert(self,index,newLine)
  119. end
  120. end
  121. function timeLine:move(otherLine,b,e)--辅助函数,转移数据
  122. --mw.log(tostring(self.time).."转移数据删除",b,e)
  123. e=e or b
  124. for i=b,e do--转移数据添加
  125. --mw.log("转移数据添加",i,self[i].time)
  126. otherLine:insert(self[i])
  127. end
  128. while e>=b do--转移数据删除
  129. --mw.log(self.time,"转移数据删除",e,self[e].time)
  130. table.remove(self,e)
  131. e=e-1
  132. end
  133. end
  134. function timeLine:_insert(newLine,index)--实际插入函数
  135. newLine.parent=self--记录父时间线
  136. table.insert(self,index,newLine)
  137. end
  138. function timeLine:insert(newLine)--插入时间函数
  139. local i=#self
  140. while i>=1 and newLine do
  141. local compareResult=newLine:compareTime(self[i])
  142. --mw.log(tostring(self[i].time).."-"..compareResult.."-"..tostring(newLine.time))
  143. if compareResult==timeLine.compareTime.inside then--包含,置入其内部
  144. --mw.log(tostring(self.time).."置入"..tostring(self[i].time).."数据"..tostring(newLine.time))
  145. newLine= self[i]:insert(newLine)
  146. elseif compareResult==timeLine.compareTime.equal then--相同。直接插入,这之后再处理
  147. break
  148. --if self:compare(newLine)~=timeLine.compare.equal then
  149. --newLine= self[i]:insert(newLine)--置入
  150. --else
  151. --break
  152. --end
  153. elseif compareResult==timeLine.compareTime.include then--需要转移数据
  154. local index=i-1
  155. while index>=1 and self[index]:compareTime(newLine)==timeLine.compareTime.inside do
  156. index=index-1
  157. end
  158. self:move(newLine,index+1,i)--转移数据的末端
  159. i=index
  160. break
  161. elseif compareResult~=timeLine.compareTime.before then--=timeCompare.before or compareResult==timeCompare.conflict then--越界或不正确(?),插入
  162. break
  163. end
  164. i=i-1
  165. --compareResult==timeCompare.after 继续
  166. end
  167. if not newLine then return end
  168. --mw.log(self.time,i+1,"追加数据",newLine.time)
  169. self:_insert(newLine,i+1)
  170. end
  171. function timeLine:currentlevel()--实际层数
  172. if self.parent then
  173. return self.parent:currentlevel()+1
  174. end
  175. return 0
  176. end
  177. function timeLine:level()--缩进层数
  178. if self.titleLevel then
  179. return 0
  180. end
  181. return self.parent:level()+1
  182. end
  183. timeLine.format.timeToText=function(self,time,parentTime)
  184. local tag=time:getMin()
  185. if parentTime and self.cut then
  186. time:coverRange(parentTime)
  187. end
  188. local timeText=time:format(self.pattern,self.ignore)
  189. if #timeText==0 then
  190. timeText=self.sameTimeTable[tag] or self.sameTimeTable[0]
  191. end
  192. return timeText
  193. end
  194. timeLine.format=setmetatable(timeLine.format,{--格式化输出文本
  195. __call=function(self,timeLine)
  196. local time=timeLine.time
  197. if not time then return nil end
  198. local timeText=self:timeToText(time,timeLine.parent and timeLine.parent.time)
  199. --mw.log(timeLine.time.from)
  200. if timeLine.titleLevel then
  201. local builder={string.rep(self.title,timeLine.titleLevel),timeText,string.rep(self.title,timeLine.titleLevel)}
  202. if timeLine.text and #timeLine.text>0 then
  203. table.insert(builder,timeLine.text)
  204. end
  205. return table.concat(builder)
  206. end
  207. local builder={self.preTime,timeText,self.afterTime}
  208. if self.alignLength>string.len(timeText) then
  209. local m,r=math.modf(self.alignLength/2-((#timeText+mw.ustring.len(timeText))/4))
  210. if m>=1 and r>0 then
  211. table.insert(builder,"   ")
  212. table.insert(builder,string.rep(" ",m-1))
  213. else
  214. table.insert(builder,string.rep(" ",m))
  215. end
  216. elseif self.alignLength>0 then
  217. table.insert(builder," ")
  218. end
  219. local level=timeLine:level()--
  220. table.insert(builder,1,string.rep(self.preRange,level))
  221. table.insert(builder,1,self.pre)
  222. table.insert(builder,timeLine.text)
  223. table.insert(builder,self.after)
  224. table.insert(builder,string.rep(self.afterRange,level))
  225. return table.concat(builder)
  226. end
  227. })
  228. function timeLine:insertText(withTimeText)--插入文本 解析为timeLine
  229. if withTimeText==nil or withTimeText=="" then return end
  230. return timeLine.create(withTimeText,self)
  231. end
  232. function timeLine:_sort()--整理
  233. local sameCount=0
  234. local index=#self
  235. while index>1 do
  236. if self[index].time==self[index-1].time then
  237. sameCount=sameCount+1
  238. else
  239. if sameCount>0 and self[index].time~=self.time then
  240. self:move(self[index],index+1,index+sameCount)
  241. end
  242. sameCount=0
  243. end
  244. index=index-1
  245. end
  246. if sameCount>0 and self[index].time~=self.time then
  247. self:move(self[index],index+1,index+sameCount)
  248. end
  249. for _,child in ipairs(self) do
  250. child:_sort()
  251. end
  252. end
  253. function timeLine:sort()--整理 同期排列
  254. if self.format.indentSameTime then
  255. self:_sort()
  256. end
  257. return self
  258. end
  259. function timeLine:toArgs(args)
  260. args=args or {}
  261. local text=self:format()
  262. args[#args+1]=text
  263. for _,child in ipairs(self) do
  264. child:toArgs(args)
  265. end
  266. return args
  267. end
  268. function timeLine:__tostring()
  269. return table.concat(self:toArgs(),timeLine.format.split)
  270. end
  271. module.timeLine=timeLine--供继承
  272. --参数预处理
  273. function module.preArgs_step(tab,state)
  274. while true do
  275. if state.gsplit[1] then
  276. local _f=state.gsplit[1]
  277. local value
  278. state.gsplit[3]=_f(state.gsplit[2],state.gsplit[3])
  279. if state.gsplit[3] then
  280. return state,state.gsplit[3]
  281. end
  282. end
  283. --下一个arg
  284. local arg=tab.args[state.index]
  285. if not arg then return nil end--结束遍历
  286. state.index=state.index+1
  287. state.gsplit={mw.text.gsplit(arg, tab.sentenceSplit)}
  288. end
  289. end
  290. function module.preArgs(args)--迭代器
  291. local tab={
  292. args=args,
  293. sentenceSplit=args.sentencesplit or args.ss or args["句段分割符"] or "\n",--识别用
  294. }
  295. local state={
  296. index=1,
  297. gsplit={},
  298. }
  299. return module.preArgs_step,tab,state
  300. end
  301. --主函数
  302. function module.timeModule(args)
  303. local from=args.from or args["原语言"]
  304. local to=args.to or args["目标语言"]
  305. local o_timezone=args.o_timezone or args.o_tz or args["原时区"]
  306. local c_timezone=args.c_timezone or args.c_tz or args["现时区"]
  307. local connect=args.timeformatrangesplit or args.tfrs or args["时间格式-时段连接符"] or "到"
  308. local timeModule=require("Module:模糊时间")
  309. timeModule.initialize(from,to,connect)
  310. return timeModule
  311. end
  312. function module.argsSet(args)--时间线参数设置
  313. --识别用
  314. timeLine.analysis.timeTextSplit={ "^%s", "^% ", }
  315. local filterAdd=function(tab,text)
  316. if text and text~="\t" and text~="\n" and text~="\r" and text~="\0" and text~="" then
  317. table.insert(tab,"^"..text)
  318. end
  319. end
  320. local timeTextSplit=args["time-textsplit"] or args.tts or args["时间-文本分割符"] or ","
  321. filterAdd(timeLine.analysis.timeTextSplit,timeTextSplit)
  322. timeLine.analysis.trim={ "^%s", "^% " }
  323. local bullet=args.bullet or args.b or args["项目符号"] or "\*"
  324. filterAdd(timeLine.analysis.trim,bullet)
  325. timeLine.analysis.title={}
  326. local timeTitle=args.timetitle or args.tt or args["时间标题符"] or "="
  327. filterAdd(timeLine.analysis.title,timeTitle)
  328. filterAdd(timeLine.analysis.timeTextSplit,timeTitle)
  329. timeLine.analysis.sameTimeTable={"^同期","^同年","^同月","^同日","^同时"}
  330. --格式化用
  331. timeLine.format.alignLength=tonumber(args.alignlength or args.al or args["对齐长度"]) or 0--18
  332. timeLine.format.pre=args.presentence or args.ps or args["文本前符"] or ""
  333. timeLine.format.after=args.aftersentence or args.as or args["文本后符"] or ""
  334. timeLine.format.preRange=args.prerange or args.pr or args["时段前符"] or bullet
  335. timeLine.format.afterRange=args.afterrange or args.ar or args["时段后符"] or ""
  336. timeLine.format.indentSameTime=((args.indentsametime or args.ist or args["时间格式-同时缩进"])~="false")--指示同时事件缩进
  337. timeLine.format.title=timeTitle
  338. timeLine.format.titleLevel=tonumber(args.titlelevel or args.tl or args["标题层级"]) --若有值,则为时间线增加分标题,值为增添的层数
  339. if timeLine.format.titleLevel then
  340. timeLine.format.titleTopLevel=tonumber(args.titletop or args.ttp or args["标题顶级层级"]) or 3 --最顶级的标题层级
  341. timeLine.format.titleUnit=tonumber(args.titleunit or args.tu or args["标题单位"]) or 3--需要标题化的最高层级单位,默认为year
  342. timeLine.format.titleUnitList=mw.text.split(args.titleunits or args.tus or args["标题单位表"] or "%C;%T;%Y;%M;%D;%H",";")
  343. timeLine._insert=timeLine._insertTitile
  344. else
  345. timeLine.format.titleLevel=nil
  346. end
  347. timeLine.format.split=args.sentencecontext or args.sc or args["句段连接符"] or "\n"--输出用
  348. timeLine.format.preTime=args.pretime or args.pt or args["时间前符"] or ""
  349. timeLine.format.afterTime=args.aftertime or args.at or args["时间后符"] or ","
  350. timeLine.format.cut=((args.timeformatcut or args.tfc or args["时间格式-省略"])~="false")--指示与父时间相同的步分省略
  351. timeLine.format.sameTimeTable={--用于识别与上一时段相同的时间--数字代表省略层级
  352. [0]="同期",
  353. ["year"]="同年",
  354. ["month"]="同月",
  355. ["day"]="同日",
  356. ["hour"]="同时",
  357. ["min"]="同时",
  358. ["second"]="同时"
  359. }
  360. timeLine.format.pattern=args.pattern or args["格式化字符串"] or "%Y%M%(Mi)%D%(Di)%H%I%S"
  361. timeLine.analysis.pattern= args.analysis_pattern or args.a_pattern or args["分析字符串"]
  362. if timeLine.analysis.pattern=="default" then
  363. timeLine.analysis.pattern=timeLine.format.pattern
  364. end
  365. local ignore=args.ignore or args["强制精确度"]
  366. if ignore=="nil" then
  367. timeLine.format.ignore=nil
  368. elseif ignore=="false" then
  369. timeLine.format.ignore=false
  370. else
  371. timeLine.format.ignore=true
  372. end
  373. local timeModule=module.timeModule(args)
  374. local totime=timeModule.toTime
  375. if timeLine.analysis.pattern then
  376. timeLine.getTime=function(text)
  377. return totime(text,timeLine.analysis.pattern)
  378. end
  379. else
  380. timeLine.getTime=totime
  381. end
  382. local time=timeModule.time
  383. timeLine.compareTime=setmetatable(mw.clone(time.compare),{--比较函数
  384. __call=function(self,timeLine1,timeLine2)
  385. --local bool,value=pcall( time.compare,timeLine1.time,timeLine2.time)
  386. return time.compare(timeLine1.time,timeLine2.time)
  387. end
  388. })
  389. end
  390. function module.toTimeLine(args)--转换为时间线
  391. module.argsSet(args)
  392. local root=timeLine.root()
  393. for _,sentence in module.preArgs(args) do
  394. root:insertText(sentence)
  395. end
  396. return root:sort()
  397. end
  398. function module.format(args)--函数:格式化参数table
  399. return module.toTimeLine(args):toArgs()
  400. end
  401. function module.toText(args)--函数:主要函数 转换为格式文本
  402. return tostring(module.toTimeLine(args))
  403. end
  404. function module.optionalArgsText(args)--获取可选参数文本
  405. local root={}
  406. for key,arg in pairs(args) do
  407. if type(key)~="number" then
  408. if key~="update" then
  409. table.insert(root,key.."="..arg)
  410. end
  411. end
  412. end
  413. return table.concat(root,"|")
  414. end
  415. function module.sortArgsSubst(args,name,fvalue)--返回排序参数后的模板,name指示模板名,fvalue指示sortargs的新值
  416. args.pre=nil
  417. args.after=nil
  418. args.pretime=nil
  419. args.aftertime=nil--避免重复问题
  420. if args.sortargs then
  421. args.sortargs=fvalue
  422. end--置为false
  423. if args["排列参数"] then
  424. args["排列参数"]=fvalue
  425. end--置为false
  426. local argsText=module.optionalArgsText(args)
  427. return "{{模板:"..name.."|"..argsText.."|\n"..module.toText(args).."\n}}"
  428. end
  429. function module.empty(args)--返回参数本身
  430. local sp=args.sentencecontext or args.sc or args["句段连接符"] or "\n"
  431. local t={}
  432. for _,arg in ipairs(args) do
  433. table.insert(t,arg)
  434. end
  435. return table.concat(t,sp)
  436. end
  437. function module._main(args, frame)--函数:主要函数
  438. local sortArgs=args["排列参数"] or args.sortargs or args.sort--排序参数,需要配合subst使用
  439. if sortArgs then
  440. if sortArgs=="false" then
  441. return module.empty(args)
  442. elseif sortArgs=="once" then
  443. return module.sortArgsSubst(args,"时间线",nil)
  444. else
  445. return module.sortArgsSubst(args,"时间线","false")
  446. end
  447. end
  448. return module.toText(args)
  449. end
  450. function module.main(frame)--函数:主要函数
  451. local args = getArgs(frame)
  452. return module._main(args, frame)
  453. end
  454. --[[function module.test()
  455. return module.main({"1年4月,吃饭饭","*1年2月,睡觉觉","1年4月,打豆豆","1年到1年,吃喝睡玩","同年4月,洗澡澡"})
  456. end]]--
  457. return module
返回顶部