alphaSDK 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 308f9e81f59e64e557f81db86a025439b2640c95c81ea39b10a02c850d6ba93f
4
+ data.tar.gz: 41385ef3b306d58452a42247c13bed04cac8e65b8647f2ec02334cc97da1f71f
5
+ SHA512:
6
+ metadata.gz: bc07f1568cdf93f77ce69eb3280faa6709a7295b4d3f721b3b60ef4dd5db56fb38ad33d1328efc51a1863c73b540d0edcaf0a6e7def2fdf7254fb76d1f0d5286
7
+ data.tar.gz: 10073fc6c998201b8493a9288108f1d82011eab00269c22b0a4c3059d6d0b4cd99f33740a514eb053faa1e38e316bbf4038a5b365bb1635f0ec3ffae2a337a29
@@ -0,0 +1,35 @@
1
+ require "net/http"
2
+ require "net/http"
3
+ require "openssl"
4
+ require "uri"
5
+ require 'Time'
6
+ require 'digest/sha1'
7
+ require 'json'
8
+ require 'async'
9
+ require_relative "./gameball/utils/request"
10
+ require_relative "./gameball/utils/helper"
11
+ require_relative "./gameball/utils/validation"
12
+ require_relative "./gameball/models/player"
13
+ require_relative "./gameball/models/event"
14
+ require_relative "./gameball/models/transaction"
15
+ require_relative "./gameball/models/referral"
16
+ require_relative "./gameball/exceptions/gameballException"
17
+
18
+
19
+ module Gameball
20
+ @api_base = "https://gb-api.azurewebsites.net"
21
+ @max_retries=1
22
+ @read_timeout=60
23
+ @keep_alive_timeout=30
24
+ @api_version="v1.0"
25
+ class << self
26
+ attr_accessor :api_key
27
+ attr_accessor :api_version
28
+ attr_accessor :transaction_key
29
+ attr_accessor :read_timeout
30
+ attr_accessor :max_retries
31
+ attr_reader :keep_alive_timeout
32
+ attr_reader :api_base
33
+
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module Gameball
2
+ class GameballError < StandardError
3
+ def initialize (msg="Something went wrong while authorizing your request")
4
+ super(msg)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Gameball
2
+ class Action
3
+ def send_action(body)
4
+ Gameball::Utils.validate(body,['playerUniqueId'],['playerAttributes','events','pointsTransaction'])
5
+ res=Gameball::Utils::request("post","/Integrations/Action",body)
6
+ unless res.kind_of? Net::HTTPSuccess
7
+ raise Gameball::GameballError.new(res) # use custom message
8
+ else
9
+ return res
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ module Gameball
2
+ class Coupon
3
+ def self.create_discount_coupon(body)
4
+ Gameball::Utils.validate(body,['playerUniqueId','transactionTime'],['startAt','endsAt','entitledCollectionIds','entitledProductIds',
5
+ 'oncePerCustomer','prerequisiteQuantityRange','prerequisiteShippingPriceRange','prerequisiteSubtotalRange',
6
+ 'prerequisiteCollectionIds','prerequisiteProductIds','code','usageLimit','value','valueType','cap'])
7
+ body["hash"]=Gameball::Utils::hashBody(playerUniqueId:body[:playerUniqueId])
8
+ res=Gameball::Utils::request("post","/Integrations/Coupon",body)
9
+ unless res.kind_of? Net::HTTPSuccess
10
+ raise Gameball::GameballError.new(res) # use custom message
11
+ else
12
+ return res
13
+ end
14
+ end
15
+ def self.validate_discount_coupon(body)
16
+ Gameball::Utils.validate(body,['playerUniqueId','code','transactionTime'])
17
+ body["hash"]=Gameball::Utils::hashBody(playerUniqueId:body[:playerUniqueId])
18
+ res=Gameball::Utils::request("post","/Integrations/Coupon/Validate",body)
19
+ unless res.kind_of? Net::HTTPSuccess
20
+ raise Gameball::GameballError.new(res) # use custom message
21
+ else
22
+ return res
23
+ end
24
+ end
25
+ def self.redeem_discount_coupon(body)
26
+ Gameball::Utils.validate(body,['playerUniqueId','code','transactionTime'])
27
+ body["hash"]=Gameball::Utils::hashBody(playerUniqueId:body[:playerUniqueId])
28
+ res=Gameball::Utils::request("post","/Integrations/Coupon/Redeem",body)
29
+ unless res.kind_of? Net::HTTPSuccess
30
+ raise Gameball::GameballError.new(res) # use custom message
31
+ else
32
+ return true
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module Gameball
2
+ class Event
3
+ # include Gameball::Request
4
+ def self.sendEvent (eventBody)
5
+ Gameball::Utils.validate(eventBody,['events','playerUniqueId'],['playerAttributes'])
6
+ if eventBody.has_key?(:playerAttributes)
7
+ # Gameball::Utils.validate(eventBody[:playerAttributes],['displayName','firstName','lastName','email','gender','mobileNumber','dateOfBirth','joinDate'],['custom'])
8
+ end
9
+ res=Gameball::Utils::request("post","/integrations/event",eventBody)
10
+ unless res.kind_of? Net::HTTPSuccess
11
+ raise Gameball::GameballError.new(res.body) # use custom message
12
+ else
13
+ return true
14
+ end
15
+ end
16
+ def self.sendEvent_async (eventBody)
17
+ Gameball::Utils.validate(eventBody,['events','playerUniqueId'],['playerAttributes'])
18
+ if eventBody.has_key?(:playerAttributes)
19
+ # Gameball::Utils.validate(eventBody[:playerAttributes],['displayName','firstName','lastName','email','gender','mobileNumber','dateOfBirth','joinDate'],['custom'])
20
+ end
21
+ res=Gameball::Utils::request_async("post","/integrations/event",eventBody)
22
+ unless res.kind_of? Net::HTTPSuccess
23
+ raise Gameball::GameballError.new(res.body) # use custom message
24
+ else
25
+ return true
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ module Gameball
2
+ class Player
3
+ # include Gameball::Request
4
+ def self.initialize_player (customerBody)
5
+ Gameball::Utils.validate(customerBody,['playerAttributes','playerUniqueId'],[])
6
+ begin
7
+ customerBody[:playerAttributes][:joinDate]=customerBody[:playerAttributes][:joinDate].iso8601
8
+ customerBody[:playerAttributes][:dateOfBirth]=customerBody[:playerAttributes][:dateOfBirth].iso8601
9
+ rescue NoMethodError => exception
10
+ p exception
11
+ raise Gameball::GameballError.new("Invalid Date Format, Please use Time and Date objects")
12
+ end
13
+
14
+ res=Gameball::Utils::request("post","/integrations/player",customerBody)
15
+ unless res.kind_of? Net::HTTPSuccess
16
+ raise Gameball::GameballError.new(res) # use custom message
17
+ else
18
+ return res
19
+ end
20
+ end
21
+ def self.get_player_info(playerUniqueId)
22
+ body={playerUniqueId:playerUniqueId}
23
+ body["bodyHashed"]=Gameball::Utils::hashBody(playerUniqueId:playerUniqueId)
24
+ res=Gameball::Utils::request("post","/integrations/Player/Info",body)
25
+ unless res.kind_of? Net::HTTPSuccess
26
+ raise Gameball::GameballError.new(res) # use custom message
27
+ else
28
+ return res
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ module Gameball
2
+ class Referral
3
+ def self.create_referral(body)
4
+ Gameball::Utils.validate(body,['playerUniqueId','playerCode'],['playerAttributes'])
5
+ if body.has_key?(:playerAttributes)
6
+ # Gameball::Utils.validate(body[:playerAttributes],['displayName','firstName','lastName','email','gender','mobileNumber','dateOfBirth','joinDate'],['custom'])
7
+ end
8
+ res=Gameball::Utils::request("post","/integrations/referral",body)
9
+ unless res.kind_of? Net::HTTPSuccess
10
+ raise Gameball::GameballError.new(res.body) # use custom message
11
+ else
12
+ return true
13
+ end
14
+ end
15
+ def self.create_referral_async(body)
16
+ Gameball::Utils.validate(body,['playerUniqueId','playerCode'],['playerAttributes'])
17
+ if body.has_key?(:playerAttributes)
18
+ # Gameball::Utils.validate(body[:playerAttributes],['displayName','firstName','lastName','email','gender','mobileNumber','dateOfBirth','joinDate'],['custom'])
19
+ end
20
+ Gameball::Utils::request_async("post","/integrations/referral",body)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,73 @@
1
+ module Gameball
2
+ class Transaction
3
+ # include Gameball::Utils
4
+ def self.get_player_balance (playerId)
5
+ hashedBody=Gameball::Utils::hashBody(playerUniqueId:playerId)
6
+ body={playerUniqueId:playerId,
7
+ bodyHashed:hashedBody
8
+ }
9
+ res=Gameball::Utils::request("post","/integrations/transaction/balance",body)
10
+ unless res.kind_of? Net::HTTPSuccess
11
+ raise Gameball::GameballError.new(res.body) # use custom message
12
+ else
13
+ return res
14
+ end
15
+ end
16
+ def self.hold_points(body)
17
+ puts body
18
+ # check if attributes are available
19
+ Gameball::Utils.validate(body,['playerUniqueId','amount','transactionTime'],['otp'])
20
+
21
+ body=Gameball::Utils::extractAttributesToHash(body)
22
+ res=Gameball::Utils::request("post","/integrations/transaction/hold",body)
23
+ unless res.kind_of? Net::HTTPSuccess
24
+ raise Gameball::GameballError.new(res.body) # use custom message
25
+ else
26
+ return res
27
+ end
28
+ end
29
+ def self.redeem_points(body)
30
+ # check if attributes are available
31
+ Gameball::Utils.validate(body,['holdReference','playerUniqueId','amount','transactionOnClientSystemId','transactionTime'],[])
32
+ body=Gameball::Utils::extractAttributesToHash(body)
33
+ res=Gameball::Utils::request("post","/integrations/transaction/redeem",body)
34
+ unless res.kind_of? Net::HTTPSuccess
35
+ raise Gameball::GameballError.new(res.body) # use custom message
36
+ else
37
+ return res
38
+ end
39
+ end
40
+ def self.reverse_transaction(body)
41
+ Gameball::Utils.validate(body,['reversedTransactionOnClientSystemId','playerUniqueId','transactionOnClientSystemId','transactionTime'],[])
42
+ body=Gameball::Utils::extractAttributesToHash(body)
43
+ res=Gameball::Utils::request("post","/integrations/transaction/cancel",body)
44
+ unless res.kind_of? Net::HTTPSuccess
45
+ raise Gameball::GameballError.new(res.body) # use custom message
46
+ else
47
+ return res
48
+ end
49
+ end
50
+ def self.reward_points(body)
51
+ Gameball::Utils.validate(body,['playerUniqueId','amount','transactionOnClientSystemId','transactionTime'],['playerAttributes'])
52
+ body=Gameball::Utils::extractAttributesToHash(body)
53
+ res=Gameball::Utils::request("post","/integrations/transaction/reward",body)
54
+ unless res.kind_of? Net::HTTPSuccess
55
+ raise Gameball::GameballError.new(res.body) # use custom message
56
+ else
57
+ return true
58
+ end
59
+ end
60
+ def self.reverse_hold(body)
61
+ # check if holdReference is in body else throw error
62
+ Gameball::Utils.validate(body,['holdReference','playerUniqueId','transactionTime'],[])
63
+
64
+ body=Gameball::Utils::extractAttributesToHash(body)
65
+ res=Gameball::Utils::request("post","/integrations/transaction/hold",body)
66
+ unless res.kind_of? Net::HTTPSuccess
67
+ raise Gameball::GameballError.new(res.body) # use custom message
68
+ else
69
+ return res
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,39 @@
1
+ module Gameball
2
+ module Utils
3
+ extend self
4
+ def hashBody(playerUniqueId:,transactionTime:"",amount:"")
5
+ # Check if transaction Key is provided else raise Exc
6
+ if !Gameball.transaction_key
7
+ raise Gameball::GameballError.new("Please provide transaction_key, try Gameball::transaction_key='your_key'") # Raise exception
8
+ else
9
+ if transactionTime==""
10
+ formatted_time=""
11
+ else
12
+ # begin
13
+ formatted_time=transactionTime.strftime("%y%m%d%H%M%S")
14
+ # rescue => exception
15
+
16
+ # end
17
+ end
18
+ end
19
+ str=playerUniqueId+":"+formatted_time+":"+amount.to_s+":"+Gameball.transaction_key
20
+ puts str
21
+ return Digest::SHA1.hexdigest (str)
22
+ end
23
+ def extractAttributesToHash(body)
24
+ playerUniqueId=body[:playerUniqueId]
25
+ amount=body[:amount]
26
+ transactionTime=body[:transactionTime]
27
+ begin
28
+ body[:transactionTime]=transactionTime.iso8601
29
+
30
+ rescue NoMethodError => exception
31
+ raise Gameball::GameballError.new("Invalid Date Formate, Please use Date and Time objects")
32
+ end
33
+ body["bodyHashed"]=Gameball::Utils::hashBody(playerUniqueId:playerUniqueId,amount:(amount||""),transactionTime:(transactionTime||""))
34
+ body
35
+ end
36
+
37
+
38
+ end
39
+ end
@@ -0,0 +1,99 @@
1
+ module Gameball
2
+ module Utils
3
+ extend self
4
+ def request(verb,path,body={})
5
+ #check for api_version and key and throw exceptions
6
+ if !Gameball.api_key
7
+ raise Gameball::GameballError.new("Please provide the api_key before making a request, try Gameball::api_key='your_key'")
8
+ end
9
+ uri=URI(Gameball.api_base+'/api'+'/'+Gameball.api_version+path)
10
+
11
+ https = Net::HTTP.new(uri.host,uri.port)
12
+ https.max_retries=Gameball.max_retries
13
+ https.read_timeout=Gameball.read_timeout
14
+ https.keep_alive_timeout=Gameball.keep_alive_timeout
15
+ https.use_ssl = true
16
+
17
+ case verb.downcase
18
+ when "post"
19
+ req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
20
+
21
+ when "get"
22
+
23
+ req = Net::HTTP::Get.new(uri.path, initheader = {'Content-Type' =>'application/json'})
24
+ when "put"
25
+
26
+ req = Net::HTTP::Put.new(uri.path, initheader = {'Content-Type' =>'application/json'})
27
+
28
+ when "delete"
29
+ req = Net::HTTP::Delete.new(uri.path, initheader = {'Content-Type' =>'application/json'})
30
+ else
31
+ puts "Please Provide a valid verb" # will later throw an exception
32
+ end
33
+ if body != {}
34
+ puts body
35
+ # begin
36
+ req.body=body.to_json
37
+ p req.body
38
+ # rescue JSON::ParserError => exception
39
+
40
+ # end
41
+
42
+ end
43
+ req['APIKey']=Gameball.api_key
44
+ res=https.request(req)
45
+ return res
46
+
47
+ end
48
+
49
+ def request_async(verb,path,body={})
50
+ #check for api_version and key and throw exceptions
51
+ if !Gameball.api_key
52
+ raise Gameball::GameballError.new("Please provide the api_key before making a request, try Gameball::api_key='your_key'")
53
+ end
54
+ uri=URI(Gameball.api_base+'/api'+'/'+Gameball.api_version+path)
55
+
56
+ https = Net::HTTP.new(uri.host,uri.port)
57
+ https.max_retries=Gameball.max_retries
58
+ https.read_timeout=Gameball.read_timeout
59
+ https.keep_alive_timeout=Gameball.keep_alive_timeout
60
+ https.use_ssl = true
61
+
62
+ case verb.downcase
63
+ when "post"
64
+ req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
65
+
66
+ when "get"
67
+
68
+ req = Net::HTTP::Get.new(uri.path, initheader = {'Content-Type' =>'application/json'})
69
+ when "put"
70
+
71
+ req = Net::HTTP::Put.new(uri.path, initheader = {'Content-Type' =>'application/json'})
72
+
73
+ when "delete"
74
+ req = Net::HTTP::Delete.new(uri.path, initheader = {'Content-Type' =>'application/json'})
75
+ else
76
+ puts "Please Provide a valid verb" # will later throw an exception
77
+ end
78
+ if body != {}
79
+ puts body
80
+ # begin
81
+ req.body=body.to_json
82
+ p req.body
83
+ # rescue JSON::ParserError => exception
84
+
85
+ # end
86
+
87
+ end
88
+ req['APIKey']=Gameball.api_key
89
+ Thread.new do
90
+ res=https.request(req)
91
+ return res
92
+ p "I am in thread"+res.body
93
+ end
94
+ # thread.join
95
+ # return res
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,18 @@
1
+ module Gameball
2
+ module Utils
3
+ extend self
4
+ def validate (hash,required,optional)
5
+ errors=[]
6
+ required.each do |val|
7
+ raise Gameball::GameballError.new("Required key: #{val.to_sym.inspect}") unless hash.has_key?(val.to_sym)
8
+ end
9
+ optional=optional+required
10
+ hash.each_key do |val|
11
+ unless optional.include?(val.to_s)
12
+ raise Gameball::GameballError.new("Unknown key: #{val.to_sym.inspect}. Valid keys are: #{optional.map(&:inspect).join(', ')}")
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,87 @@
1
+ require_relative './gameball'
2
+ Gameball::api_key="7c7636658209418c9a82306a421f76a5"
3
+ Gameball::api_version="v2.0"
4
+ Gameball::transaction_key="26e1967d89114388bdd1772587c336c8"
5
+ # res=Gameball::Transaction.get_player_balance("uniqueKey00")
6
+ res=Gameball::Player.initialize_player({playerUniqueId:"uniquekeys120",playerAttributes:
7
+ {displayName:"Souidan",firstName:"Souidan1",lastName:"Souidan2",email:"alisouidan@gmail.com",
8
+ gender:"Male",mobileNumber:"+201002580909",
9
+ dateOfBirth:Date.parse("10/10/2010"),joinDate:Time.now.utc
10
+ }})
11
+ # res=Gameball::Transaction.hold_points({
12
+ # playerUniqueId:"uniqueKey00",
13
+ # amount:2,
14
+ # transactionTime:Time.now.utc
15
+ # })
16
+ # res=Gameball::Transaction.redeem_points({
17
+ # holdReference:"c61153e4-fc79-4b1c-adce-f789bc061fe9",
18
+ # playerUniqueId:"uniqueKey00",
19
+ # amount:2,
20
+ # transactionOnClientSystemId:12,
21
+ # transactionTime:Time.now.utc
22
+ # })
23
+ # res=Gameball::Transaction.reverse_transaction({
24
+ # playerUniqueId:"uniqueKey00",
25
+ # transactionOnClientSystemId:12,
26
+ # reversedTransactionOnClientSystemId:12,
27
+ # transactionTime:Time.now.utc
28
+ # })
29
+ # res=Gameball::Transaction.reverse_hold({
30
+ # playerUniqueId:"uniqueKey00",
31
+ # holdReference:"80144eaa-8e5b-4c6b-8f4d-58f0d8766797",
32
+ # transactionTime:Time.now.utc
33
+ # })
34
+
35
+ # res=Gameball::Referral.create_referral({
36
+ # playerCode:"CODE11",
37
+ # playerUniqueId:"player456"
38
+ # }
39
+ # )
40
+ # res=Gameball::Player.get_player_info("uniqueKey00")
41
+ # res=Gameball::Transaction.reward_points({
42
+ # playerUniqueId:"uniqueKey00",
43
+ # amount:100,
44
+ # transactionTime:Time.now.utc,
45
+ # transactionOnClientSystemId:"1232344",
46
+
47
+ # })
48
+ # res=Gameball::Event.sendEvent({
49
+ # events:{
50
+ # reserve:{
51
+ # rooms:2
52
+ # }
53
+ # },
54
+ # playerUniqueId:" player123",
55
+ # playerAttributes:{
56
+ # displayName:" Jon Snow",
57
+ # email:"jon.snow@example.com",
58
+ # dateOfBirth:"1980-09-19T00:00:00.000Z",
59
+ # joinDate:"2019-09-19T21:06:29.158Z",
60
+ # custom:{
61
+ # location:"Miami",
62
+ # graduationDate:"2018-07-04T21:06:29.158Z",
63
+ # isMarried:false
64
+ # }
65
+
66
+ # }
67
+ # }
68
+
69
+
70
+ # )
71
+ # res=Gameball::Event.sendEvent({
72
+ # events:{view_product_page:{customer_id:"123",product_id:"123",product_title:"title",product_vendor:"vendor",shop_name:"shop"}},
73
+ # playerUniqueId:"uniquekeys120",
74
+ # playerAttributes:{displayName:"Souidan",firstName:"Souidan1",lastName:"Souidan2",email:"alisouidan1@gmail.com",gender:"Male",mobileNumber:"+201002580909",dateOfBirth:"0123",joinDate:Time.now.utc}
75
+ # })
76
+ p res.body
77
+ # p res
78
+ # # puts Gameball::Helper::hashBody(playerUniqueId:"123",transactionId:"34",transactionTime:Time.now.utc)
79
+ # res=Gameball::Event.sendEvent({
80
+ # events:{view_product_page:{customer_id:"123",product_id:"123",product_title:"title",product_vendor:"vendor",shop_name:"shop"}},
81
+ # playerUniqueId:"uinqueKeys123"
82
+ # }) #Check the sinatra server window for the output.
83
+ # p res
84
+ # sleep 5 #Do some time consuming task.
85
+ # p res
86
+ # puts "Sending response..."
87
+ # #The response(which the rails app ignores).
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alphaSDK
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Souidan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: SDK
14
+ email: alsouidan@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/gameball.rb
20
+ - lib/gameball/exceptions/gameballException.rb
21
+ - lib/gameball/models/action.rb
22
+ - lib/gameball/models/coupon.rb
23
+ - lib/gameball/models/event.rb
24
+ - lib/gameball/models/gameballResponse.rb
25
+ - lib/gameball/models/player.rb
26
+ - lib/gameball/models/referral.rb
27
+ - lib/gameball/models/transaction.rb
28
+ - lib/gameball/utils/helper.rb
29
+ - lib/gameball/utils/request.rb
30
+ - lib/gameball/utils/validation.rb
31
+ - lib/testFile.rb
32
+ homepage: https://rubygems.org/gems/hola
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.0.3
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Test
55
+ test_files: []