EventChart 2022.5.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/eventchart +20 -0
- data/lib/extremeunzip.zzaqsu.rb +35 -0
- data/lib/extremezip.zzaqsv.rb +322 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b6e9b221c77c9b657e64b9d5c2389b76509d51d7fdfb1a098a59c79c15918ca2
|
4
|
+
data.tar.gz: 2aaaf35571613983885231c12fbc49be2654ddfbdecc462770f032b940bc7218
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 78ce77d93f4f9680f31124a7ccefd4f9d172b1a2c3f1ec9a02ab9af3b0a2188edbafe7e69286ddc074f477506e48c126ec5285baa72b354d74af2711a94f7ad7
|
7
|
+
data.tar.gz: 2d2451704e1253ef29d9ea750d6cb841c052bb729350732e028536387ccec5acc16e2fe4cf272e79c1043fccdb41bc3621503c632f422e2d1a78338532f2a3d2
|
data/bin/eventchart
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'extremeunzip.zzaqsu'
|
4
|
+
|
5
|
+
if ARGV.empty? # 未指定命令行参数。
|
6
|
+
else # 指定了命令行参数。
|
7
|
+
returnCode = 0 # 失败
|
8
|
+
$rootPath = ARGV[0] # 记录要打包的目录树的根目录。
|
9
|
+
|
10
|
+
exuzObject = ExtremeUnZip.new # 解压对象
|
11
|
+
|
12
|
+
result = exuzObject.exuz($rootPath) # 解压
|
13
|
+
|
14
|
+
if result # 解压成功
|
15
|
+
else # 解压失败
|
16
|
+
returnCode = 1 # 失败
|
17
|
+
end #if result # 解压成功
|
18
|
+
|
19
|
+
exit returnCode # 退出
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'victoriafresh'
|
4
|
+
require 'cbor'
|
5
|
+
require 'lzma'
|
6
|
+
require 'get_process_mem'
|
7
|
+
|
8
|
+
class ExtremeUnZip
|
9
|
+
# 解压
|
10
|
+
def exuz(rootPath)
|
11
|
+
result = true # 解压结果
|
12
|
+
|
13
|
+
currentBlockFile = File.new(rootPath, 'rb') # 打开文件
|
14
|
+
|
15
|
+
@wholeFileContent = currentBlockFile.read # 读取全部内容
|
16
|
+
|
17
|
+
currentBlockFile.close # 关闭文件
|
18
|
+
|
19
|
+
wholeCborByteArray = @wholeFileContent # 从第5个到末尾
|
20
|
+
|
21
|
+
begin # 可能出错。
|
22
|
+
options = {:tolerant => true}
|
23
|
+
|
24
|
+
wholeCbor = CBOR.decode(wholeCborByteArray, options) # 解码
|
25
|
+
|
26
|
+
puts wholeCbor
|
27
|
+
|
28
|
+
result =true # 解压成功
|
29
|
+
rescue EOFError => e # 文件内容提前到末尾。一般是压缩包文件未传输完全 。
|
30
|
+
puts "Error: the exz file may be incomplete." # 报告错误。文件可能不完整。
|
31
|
+
|
32
|
+
result = false # 失败
|
33
|
+
end #begin # 可能出错。
|
34
|
+
end # def exuz(rootPath)
|
35
|
+
end # class ExtremeUnZip
|
@@ -0,0 +1,322 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'victoriafresh'
|
5
|
+
require 'cbor' # CBOR
|
6
|
+
require 'lzma' # LZMA
|
7
|
+
require 'etc' # cpu amount
|
8
|
+
require 'cod'
|
9
|
+
require 'uuid'
|
10
|
+
require 'get_process_mem'
|
11
|
+
require 'pathname'
|
12
|
+
|
13
|
+
def checkMemoryUsage(lineNumber)
|
14
|
+
mem = GetProcessMem.new
|
15
|
+
|
16
|
+
puts("#{lineNumber} , Memory: #{mem.mb}, process id: #{Process.pid}"); # Debug
|
17
|
+
end # def checkMemoryUsage
|
18
|
+
|
19
|
+
class ExtremeZip
|
20
|
+
def initialize
|
21
|
+
@wholeCbor = {} # 整个CBOR结构
|
22
|
+
@vfsDataList = [] # 数据块压缩块列表
|
23
|
+
@filePartCounter = 0 # 文件分块计数器
|
24
|
+
@responsePipeList = [] # 任务回复管道列表
|
25
|
+
@processIdList = [] # 子进程编号列表。
|
26
|
+
@processTimestamp = Time.new.to_i # 记录进程启动的时间戳。
|
27
|
+
|
28
|
+
@maxSubProcessAmount = Etc.nprocessors # 获取最大的子进程个数
|
29
|
+
|
30
|
+
@dataBlockLength = 33554432 # 数据块单元长度, 32MiB
|
31
|
+
|
32
|
+
@clipDownloader = VictoriaFresh.new # 创建下载器。
|
33
|
+
|
34
|
+
@clipDownloader.diskFlush = true # 向磁盘写入缓存
|
35
|
+
@clipDownloader.diskMultiFile = true # 写多个磁盘文件
|
36
|
+
@clipDownloader.diskFileName = 'victoriafreshdata.v.' # 磁盘文件名前缀
|
37
|
+
@clipDownloader.diskFlushSize = @dataBlockLength # 磁盘文件大小
|
38
|
+
@clipDownloader.ignoreFileName= '.exzignore' # 设置用于指定忽略文件列表的文件名。
|
39
|
+
end # def initialize
|
40
|
+
|
41
|
+
# 压缩目录数据。
|
42
|
+
def compressVfsMenu(victoriaFresh)
|
43
|
+
replyByteArray = victoriaFresh.to_cbor # #打包成字节数组。
|
44
|
+
|
45
|
+
# 压缩目录数据并放入CBOR:
|
46
|
+
compressedVfsMenu = LZMA.compress(replyByteArray) # 压缩目录数据
|
47
|
+
|
48
|
+
@wholeCbor['vfsMenu'] = compressedVfsMenu # 加入目录
|
49
|
+
end # compressVfsMenu(victoriaFresh) # 压缩目录数据。
|
50
|
+
|
51
|
+
# 加入基本文件信息
|
52
|
+
def addBasicFileInformation
|
53
|
+
@wholeCbor['version'] = 251 # 文件格式版本号
|
54
|
+
|
55
|
+
uuid = UUID.new # 获取生成器
|
56
|
+
@wholeCbor['uuid'] = uuid.generate # 指定本个压缩包的唯一编号
|
57
|
+
|
58
|
+
@wholeCbor['website']='https://rubygems.org/gems/EXtremeZip' # 加入网站地址
|
59
|
+
|
60
|
+
@wholeCbor['vfsDataListStart']=198910 # 压缩 VFS 数据列表起始位置。
|
61
|
+
end # addBasicFileInformation # 加入基本文件信息
|
62
|
+
|
63
|
+
def writeStamp(rootPath) # 更新时间戳文件
|
64
|
+
directoryPathName=Pathname.new(rootPath) #构造路径名字对象。
|
65
|
+
datastore= "#{directoryPathName.expand_path}/.exzstamp" # 配置文件路径
|
66
|
+
puts "writing stamp file: #{datastore}" # Debug
|
67
|
+
|
68
|
+
#stamp = wholeCbor['timestamp'] # 获取时间戳
|
69
|
+
stampCbor={} # 时间戳对象。
|
70
|
+
stampCbor['timestamp']= @processTimestamp # 设置时间戳。
|
71
|
+
|
72
|
+
compressed= stampCbor.to_cbor
|
73
|
+
|
74
|
+
extremeZipOutputFile = File.new(datastore, 'wb') # 创建文件
|
75
|
+
extremeZipOutputFile.syswrite(compressed) # 写入文件
|
76
|
+
extremeZipOutputFile.close # 关闭文件
|
77
|
+
|
78
|
+
end # writeStamp # 更新时间戳文件
|
79
|
+
|
80
|
+
def loadStamp(rootPath) # 读取时间戳阈值。
|
81
|
+
stamp=0 # 默认值。
|
82
|
+
fileExists=false # 文件是否存在
|
83
|
+
|
84
|
+
directoryPathName=Pathname.new(rootPath) #构造路径名字对象。
|
85
|
+
|
86
|
+
isFile=directoryPathName.file? #是否是文件。
|
87
|
+
|
88
|
+
unless isFile #是文件就跳过。
|
89
|
+
#陈欣
|
90
|
+
|
91
|
+
datastore= "#{directoryPathName.expand_path}/.exzstamp" # 配置文件路径
|
92
|
+
puts "reading stamp file: #{datastore}" # Debug
|
93
|
+
|
94
|
+
begin # 尝试读取。
|
95
|
+
|
96
|
+
#陈欣
|
97
|
+
|
98
|
+
currentBlockFile = File.new(datastore, 'rb') # 打开文件
|
99
|
+
|
100
|
+
fileExists=true # 文件存在
|
101
|
+
|
102
|
+
stampFileContent = currentBlockFile.read # 读取全部内容
|
103
|
+
|
104
|
+
currentBlockFile.close # 关闭文件
|
105
|
+
|
106
|
+
options = {:tolerant => true}
|
107
|
+
|
108
|
+
wholeCbor = CBOR.decode(stampFileContent, options) # 解码
|
109
|
+
|
110
|
+
puts wholeCbor # Debug
|
111
|
+
puts wholeCbor.inspect # Debug
|
112
|
+
|
113
|
+
stamp = wholeCbor['timestamp'].to_i # 获取时间戳
|
114
|
+
rescue Errno::ENOENT, TypeError
|
115
|
+
end
|
116
|
+
end #unless isFile #是文件就跳过。
|
117
|
+
|
118
|
+
return stamp, fileExists # 返回时间戳。
|
119
|
+
end #loadStamp(rootPath) # 读取时间戳阈值。
|
120
|
+
|
121
|
+
# 压缩
|
122
|
+
def exz(rootPath)
|
123
|
+
timestampTHreshold, fileExists=loadStamp(rootPath) # 读取时间戳阈值。
|
124
|
+
|
125
|
+
puts "threshold: #{timestampTHreshold}" # Debug
|
126
|
+
|
127
|
+
#陈欣
|
128
|
+
|
129
|
+
if (timestampTHreshold > 0) # 有效的时间戳
|
130
|
+
@clipDownloader.timestampThreshold=timestampTHreshold # 设置文件时间戳阈值。
|
131
|
+
end #if (timestampTHreshold > 0) # 有效的时间戳
|
132
|
+
|
133
|
+
puts "threshold vfs: #{@clipDownloader.timestampThreshold}" # Debug
|
134
|
+
|
135
|
+
if fileExists # 存在文件,则表明将要发生增量压缩
|
136
|
+
@wholeCbor['incremental']=true # 是增量压缩。
|
137
|
+
end # if fileExists # 存在文件,则表明用户要求增量压缩
|
138
|
+
|
139
|
+
@wholeCbor['timestamp']=@processTimestamp # 记录进程启动的时间戳。
|
140
|
+
|
141
|
+
victoriaFresh, = @clipDownloader.checkOnce(rootPath) # 打包该目录树。
|
142
|
+
|
143
|
+
@filePartAmount = @clipDownloader.currentDiskFlushSuffix # 获取文件个数
|
144
|
+
|
145
|
+
compressVfsMenu(victoriaFresh) # 压缩目录数据。
|
146
|
+
|
147
|
+
addBasicFileInformation # 加入基本文件信息
|
148
|
+
|
149
|
+
processIdList, responsePipeList = launchSubProcesses # 启动子进程。
|
150
|
+
|
151
|
+
receiveCompressedVfsDataList(processIdList, responsePipeList) # 接收压缩后的数据块列表
|
152
|
+
|
153
|
+
checkMemoryUsage(155)
|
154
|
+
@wholeCbor['vfsDataList'] = @vfsDataList # 加入数据
|
155
|
+
|
156
|
+
wholeFileContent = 'exz' + "\0" + @wholeCbor.to_cbor # 追加CBOR字节数组
|
157
|
+
|
158
|
+
vfsDataListStart=wholeFileContent.length # 按照现在的序列化情况,计算出来的起始位置。
|
159
|
+
|
160
|
+
while (vfsDataListStart!=@wholeCbor['vfsDataListStart']) # 计算出的偏移不一致
|
161
|
+
@wholeCbor['vfsDataListStart']=vfsDataListStart # 使用新的值
|
162
|
+
wholeFileContent = 'exz' + "\0" + @wholeCbor.to_cbor # 追加CBOR字节数组
|
163
|
+
vfsDataListStart=wholeFileContent.length # 按照现在的序列化情况,计算出来的起始位置。
|
164
|
+
end
|
165
|
+
|
166
|
+
# 写入文件:
|
167
|
+
writeFile(wholeFileContent, victoriaFresh) # 写入文件内容
|
168
|
+
|
169
|
+
appendVfsDataList victoriaFresh # 追加压缩块列表数据。
|
170
|
+
|
171
|
+
if fileExists # 存在文件,则表明将要发生增量压缩
|
172
|
+
writeStamp (rootPath) # 更新时间戳文件
|
173
|
+
end # if fileExists # 存在文件,则表明用户要求增量压缩
|
174
|
+
|
175
|
+
end # def exz(rootPath)
|
176
|
+
|
177
|
+
# 写入压缩块文件
|
178
|
+
def writeCompressBlock(compressed, processCounter)
|
179
|
+
extremeZipOutputFile = File.new("comressed.#{processCounter}.cex", 'wb') # 创建文件
|
180
|
+
extremeZipOutputFile.syswrite(compressed) # 写入文件
|
181
|
+
extremeZipOutputFile.close # 关闭文件
|
182
|
+
end
|
183
|
+
|
184
|
+
# 追加压缩块列表数据。
|
185
|
+
def appendVfsDataList (victoriaFresh)
|
186
|
+
extremeZipOutputFile = File.new("#{victoriaFresh['name']}.exz", 'ab') # 打开文件
|
187
|
+
|
188
|
+
processCounter=0 # 块计数器。
|
189
|
+
|
190
|
+
@wholeCbor['vfsDataList'].each do
|
191
|
+
#extremeZipOutputFile = File.new("comressed.#{processCounter}.cex", 'wb') # 创建文件
|
192
|
+
|
193
|
+
currentBlockFile = File.new("comressed.#{processCounter}.cex", 'rb') # 打开文件
|
194
|
+
|
195
|
+
wholeFileContent = currentBlockFile.read # 读取全部内容
|
196
|
+
|
197
|
+
currentBlockFile.close # 关闭文件
|
198
|
+
File.delete(currentBlockFile) # 删除数据块文件
|
199
|
+
|
200
|
+
#wholeFileContent=File.read("comressed.#{processCounter}.cex", 'rb') # 读取压缩块。
|
201
|
+
|
202
|
+
puts "wirte file contetn length: #{wholeFileContent.length}" # Debghu
|
203
|
+
|
204
|
+
extremeZipOutputFile.syswrite(wholeFileContent) # 写入文件
|
205
|
+
|
206
|
+
processCounter += 1 # 计数
|
207
|
+
end
|
208
|
+
|
209
|
+
extremeZipOutputFile.close # 关闭文件
|
210
|
+
end
|
211
|
+
|
212
|
+
# 写入文件内容
|
213
|
+
def writeFile(wholeFileContent, victoriaFresh)
|
214
|
+
extremeZipOutputFile = File.new("#{victoriaFresh['name']}.exz", 'wb') # 创建文件
|
215
|
+
extremeZipOutputFile.syswrite(wholeFileContent) # 写入文件
|
216
|
+
extremeZipOutputFile.close # 关闭文件
|
217
|
+
end # writeFile(wholeFileContent, victoriaFresh) #写入文件内容
|
218
|
+
|
219
|
+
# 接收压缩后的数据块列表
|
220
|
+
def receiveCompressedVfsDataList(processIdList, responsePipeList)
|
221
|
+
processCounter = 0 # 子进程计数器
|
222
|
+
|
223
|
+
while (processCounter<@filePartAmount) # 并不是所有分块都被处理完毕了。
|
224
|
+
currentSubProcess=processIdList[processCounter] # 获取子进程对象
|
225
|
+
#processIdList.each do |currentSubProcess|
|
226
|
+
compressed = receiveFromSubProcess(currentSubProcess, responsePipeList, processCounter) # 从子进程中读取数据,并终止子进程
|
227
|
+
|
228
|
+
#写入当前压缩块到文件系统中去作为缓存。陈欣
|
229
|
+
writeCompressBlock(compressed, processCounter) # 写入压缩块文件
|
230
|
+
|
231
|
+
blockInfo={} # 块信息
|
232
|
+
blockInfo['length']=compressed.length # 记录长度
|
233
|
+
|
234
|
+
puts "block length: #{blockInfo['length']}" # Debug
|
235
|
+
|
236
|
+
@vfsDataList << blockInfo # 加入数据块列表中
|
237
|
+
checkMemoryUsage(150)
|
238
|
+
|
239
|
+
processCounter += 1 # 子进程计数
|
240
|
+
|
241
|
+
if (@filePartCounter<@filePartAmount) # 还有一些分块尚未交给子进程进行处理
|
242
|
+
schedule1Block(@filePartCounter) # 再启动一个子进程
|
243
|
+
end # if (@filePartCounter<@filePartAmount) # 还有一些分块尚未交给子进程进行处理
|
244
|
+
end # processIdList.each do |currentSubProcess|
|
245
|
+
end # receiveCompressedVfsDataList # 接收压缩后的数据块列表
|
246
|
+
|
247
|
+
# 读取块文件内容
|
248
|
+
def readBlockFile(filePartCounter)
|
249
|
+
currentBlockFile = File.new(@clipDownloader.diskFileName + filePartCounter.to_s, 'rb') # 打开文件
|
250
|
+
|
251
|
+
currentBlockData = currentBlockFile.read # 读取全部内容
|
252
|
+
|
253
|
+
currentBlockFile.close # 关闭文件
|
254
|
+
|
255
|
+
File.delete(currentBlockFile) # 删除数据块文件
|
256
|
+
|
257
|
+
currentBlockData
|
258
|
+
end
|
259
|
+
|
260
|
+
# 计划一个块的压缩计算
|
261
|
+
def schedule1Block(filePartCounter)
|
262
|
+
currentBlockData = readBlockFile(filePartCounter) # 读取块文件内容
|
263
|
+
|
264
|
+
currentResponsePipe = Cod.pipe # 任务回复管道
|
265
|
+
|
266
|
+
p1 = fork do # 复制出子进程
|
267
|
+
compressInSubProcess(currentBlockData, currentResponsePipe) # 在子进程中具体执行的压缩代码
|
268
|
+
end # p1 = fork do #复制出子进程
|
269
|
+
|
270
|
+
# processDataLength += @dataBlockLength # 计数
|
271
|
+
checkMemoryUsage(130)
|
272
|
+
|
273
|
+
# 记录管道:
|
274
|
+
# taskPipeList << currentTaskPipe
|
275
|
+
@responsePipeList << currentResponsePipe # 记录回复管道
|
276
|
+
|
277
|
+
@processIdList << p1 # 记录到子进程列表中
|
278
|
+
|
279
|
+
@filePartCounter += 1 # 计数
|
280
|
+
|
281
|
+
[currentResponsePipe, p1]
|
282
|
+
end # schedule1Block(filePartCounter) # 计划一个块的压缩计算
|
283
|
+
|
284
|
+
# 启动子进程。
|
285
|
+
def launchSubProcesses
|
286
|
+
while ((@filePartCounter < @filePartAmount) && (@filePartCounter<@maxSubProcessAmount)) # 未处理完毕,并且未达到最大子进程个数
|
287
|
+
currentResponsePipe, p1 = schedule1Block(@filePartCounter) # 计划一个块的压缩计算
|
288
|
+
end # while processDataLength < victoriaFreshData.byte_size do #未处理完毕
|
289
|
+
|
290
|
+
[@processIdList, @responsePipeList]
|
291
|
+
end # launchSubProcesses # 启动子进程。
|
292
|
+
|
293
|
+
# 在子进程中具体执行的压缩代码
|
294
|
+
def compressInSubProcess(currentBlockData, currentResponsePipe)
|
295
|
+
checkMemoryUsage(115) # Debug
|
296
|
+
currentBlockDataToCompress = currentBlockData # 读取数据块
|
297
|
+
|
298
|
+
currentCompressedVfsData = LZMA.compress(currentBlockDataToCompress) # 压缩当前块
|
299
|
+
|
300
|
+
checkMemoryUsage(120)
|
301
|
+
puts("compressed data length: #{currentCompressedVfsData.bytesize}") # Debug.
|
302
|
+
|
303
|
+
currentResponsePipe.put currentCompressedVfsData # 将压缩后的数据块写入到回复管道中
|
304
|
+
|
305
|
+
puts("finished #{Process.pid}") # Debug
|
306
|
+
end # compressInSubProcess(currentBlockData, currentResponsePipe) # 在子进程中具体执行的压缩代码
|
307
|
+
|
308
|
+
# 从子进程中读取数据,并终止子进程
|
309
|
+
def receiveFromSubProcess(currentSubProcess, responsePipeList, processCounter)
|
310
|
+
puts("waiting #{currentSubProcess}") # Debug
|
311
|
+
checkMemoryUsage(140)
|
312
|
+
|
313
|
+
currentResponsePipe = responsePipeList[processCounter] # 任务回复管道
|
314
|
+
|
315
|
+
currentCompressedVfsDataFromSubProcess = currentResponsePipe.get # 读取压缩后数据
|
316
|
+
checkMemoryUsage(145)
|
317
|
+
|
318
|
+
Process.waitpid(currentSubProcess) # 等待该个子进程
|
319
|
+
|
320
|
+
currentCompressedVfsDataFromSubProcess
|
321
|
+
end # receiveFromSubProcess(currentSubProcess) # 从子进程中读取数据,并终止子进程
|
322
|
+
end # class ExtremeZip
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: EventChart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2022.5.30
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hxcan Cai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cod
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.6.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: get_process_mem
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.7
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.2.7
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ruby-lzma
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: notifier
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.5.2
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.5.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: uuid
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.3.9
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.3.9
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: VictoriaFreSh
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2022.2.24
|
90
|
+
- - "~>"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 2022.2.24
|
93
|
+
type: :runtime
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 2022.2.24
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 2022.2.24
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: hx_cbor
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2021.8.20
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2021.8.20
|
117
|
+
description: EventChart
|
118
|
+
email: caihuosheng@gmail.com
|
119
|
+
executables:
|
120
|
+
- eventchart
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- bin/eventchart
|
125
|
+
- lib/extremeunzip.zzaqsu.rb
|
126
|
+
- lib/extremezip.zzaqsv.rb
|
127
|
+
homepage: http://rubygems.org/gems/EventChart
|
128
|
+
licenses:
|
129
|
+
- MIT
|
130
|
+
metadata: {}
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubygems_version: 3.0.9
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: EventChart
|
150
|
+
test_files: []
|