Skip to content
This repository has been archived by the owner on Apr 26, 2023. It is now read-only.

Commit

Permalink
Added parsing of skip offset for VAST ad
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanTysiachnik committed Feb 9, 2019
1 parent 893707f commit 21199de
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 13 deletions.
2 changes: 1 addition & 1 deletion PlayerCore
8 changes: 4 additions & 4 deletions VerizonVideoPartnerSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1070,15 +1070,15 @@
DE1685D71CE7308500492A90 /* vast parser */ = {
isa = PBXGroup;
children = (
DEF02B511D1EC0AD001F64EE /* VASTModel.swift */,
DE1685DC1CE732D600492A90 /* VASTParser.swift */,
DE1685E61CE76A5D00492A90 /* VASTParserTests.swift */,
DE1685E41CE768E600492A90 /* VASTExampleCDATA.xml */,
DE1FD9CE1CE7737900C0B7BC /* VASTMissedCorrectType.xml */,
DE4539411D09644D00317632 /* XMLParser.swift */,
DEF02B511D1EC0AD001F64EE /* VASTModel.swift */,
DEF02B581D22970A001F64EE /* VAST1.xml */,
06BF541620A062E300B98A6D /* VASTVpaid.xml */,
DE1685E41CE768E600492A90 /* VASTExampleCDATA.xml */,
DE1FD9CE1CE7737900C0B7BC /* VASTMissedCorrectType.xml */,
067209D921B6BE710086CDBE /* VASTVerificationInExtension.xml */,
06BF541620A062E300B98A6D /* VASTVpaid.xml */,
B418F5461ECB267B00C9131D /* VASTWrapper.xml */,
067209DA21B6BE710086CDBE /* VASTWrapperWithExtension.xml */,
);
Expand Down
1 change: 1 addition & 0 deletions sources/advertisements/MidrollDetectorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class MidrollDetectorTests: QuickSpec {
scalable: true,
maintainAspectRatio: true)],
vpaidMediaFiles: [],
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: .init(),
Expand Down
4 changes: 2 additions & 2 deletions sources/advertisements/VAST1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
<Impression><![CDATA[http://localhost:3000/0/pixels/pixel.php?name=noname_impression&random=[CACHE_BUSTER]]]></Impression>
<Creatives>
<Creative id="55414">
<Linear>
<Duration>00:00:30</Duration>
<Linear skipoffset="01:01:03.123">
<Duration>02:00:30</Duration>
<TrackingEvents>
<Tracking event="creativeView"><![CDATA[http://localhost:3000/6/beacons/vast/creativeView.gif]]></Tracking>
<Tracking event="start"><![CDATA[http://localhost:3000/6/beacons/vast/start.gif]]></Tracking>
Expand Down
1 change: 1 addition & 0 deletions sources/advertisements/VASTModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extension PlayerCore.Ad.VASTModel {
adVerifications: self.adVerifications + verifications,
mp4MediaFiles: mp4MediaFiles,
vpaidMediaFiles: vpaidMediaFiles,
skipOffset: skipOffset,
clickthrough: clickthrough,
adParameters: adParameters,
pixels: self.pixels.merge(with: pixels),
Expand Down
28 changes: 28 additions & 0 deletions sources/advertisements/VASTParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum VASTParser {
var adParameters: String?
var mp4MediaFiles: [PlayerCore.Ad.VASTModel.MP4MediaFile] = []
var vpaidMediaFiles: [PlayerCore.Ad.VASTModel.VPAIDMediaFile] = []
var skipOffset: PlayerCore.Ad.VASTModel.SkipOffset = .none
}

struct AdVerification {
Expand Down Expand Up @@ -134,6 +135,16 @@ enum VASTParser {
}

delegate.didStartElement = .some { (name, attr) -> Void in
if let skipOffset = attr["skipoffset"] {
if skipOffset.contains("%") {
guard let value = Int(skipOffset.replacingOccurrences(of: "%", with: "")) else { return }
inlineContext.skipOffset = .percentage(value)
} else if skipOffset.contains(":") {
guard let value = parseTime(from: skipOffset) else { return }
inlineContext.skipOffset = .time(value)
}
}

switch name {
case "Extensions":
delegateStack.push(XML.Delegate(setup: { delegate in
Expand Down Expand Up @@ -449,6 +460,7 @@ enum VASTParser {
with: adId,
to: { context in
delegateStack.pop()

guard result == nil else { fatalError("Result overwrite detected") }
guard !context.vpaidMediaFiles.isEmpty || !context.mp4MediaFiles.isEmpty else { return }

Expand All @@ -466,6 +478,7 @@ enum VASTParser {
let model = PlayerCore.Ad.VASTModel(adVerifications: adVerifications,
mp4MediaFiles: context.mp4MediaFiles,
vpaidMediaFiles: context.vpaidMediaFiles,
skipOffset: context.skipOffset,
clickthrough: context.clickthroughURL,
adParameters: context.adParameters,
pixels: context.pixels,
Expand All @@ -491,6 +504,21 @@ enum VASTParser {

return delegateStack
}

static func parseTime(from string: String) -> Double? {
let components = string.components(separatedBy: ":")
guard components.count == 3 else { return nil }
return components
.compactMap(Double.init)
.enumerated()
.map {
let multiplier = pow(60, abs($0.offset - 2)) as NSNumber
return $0.element * multiplier.doubleValue
}
.reduce(0.0, +)
}


//swiftlint:disable line_length
//swiftlint:enable function_body_length
//swiftlint:enable cyclomatic_complexity
Expand Down
18 changes: 16 additions & 2 deletions sources/advertisements/VASTParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class VASTParserTests: XCTestCase {
guard case let .inline(inlineModel) = model else { return XCTFail() }
guard let url = inlineModel.mp4MediaFiles.first?.url.absoluteString else { return XCTFail() }
XCTAssertEqual(url,
"https://dev.example.com/videos/2018/video_example_1280x720.mp4")
"https://dev.example.com/videos/2018/video_example_1280x720.mp4")
XCTAssertEqual(inlineModel.id, "4203085")
}

Expand Down Expand Up @@ -69,7 +69,7 @@ class VASTParserTests: XCTestCase {
let vast = getVAST(atPath: "VAST1")
guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail() }
guard case .inline(let inlineModel) = model else { return XCTFail() }

XCTAssertEqual(inlineModel.adVerifications.count, 1)
guard let adVerification = inlineModel.adVerifications.first else { return XCTFail("Missing AdVerification") }

Expand Down Expand Up @@ -124,4 +124,18 @@ class VASTParserTests: XCTestCase {
XCTAssertEqual(vpaidModel.pixels.close.first?.absoluteString, url + "close.gif")
XCTAssertEqual(vpaidModel.pixels.collapse.first?.absoluteString, url + "collapse.gif")
}

func testParseAdSkipInTime() {
let vast = getVAST(atPath: "VAST1")
guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail("Failed to parse VAST VPAID xml") }
guard case let .inline(vpaidModel) = model else { return XCTFail() }
XCTAssertEqual(vpaidModel.skipOffset, .time(3663.123))
}

func testParseAdSkipInPersentage() {
let vast = getVAST(atPath: "VASTExampleCDATA")
guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail("Failed to parse VAST VPAID xml") }
guard case let .inline(vpaidModel) = model else { return XCTFail() }
XCTAssertEqual(vpaidModel.skipOffset, .percentage(32))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class FinishVRMGroupProcessingControllerTest: XCTestCase {
adModel = .init(adVerifications: [],
mp4MediaFiles: [],
vpaidMediaFiles: [],
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: .init(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ParseVRMItemControllerTest: XCTestCase {
let result = PlayerCore.Ad.VASTModel(adVerifications: [],
mp4MediaFiles: [],
vpaidMediaFiles: [],
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: AdPixels(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class VRMProcessingControllerTest: XCTestCase {
adModel = .init(adVerifications: [],
mp4MediaFiles: [],
vpaidMediaFiles: [],
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: .init(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ class VRMSelectFinalResultControllerTest: XCTestCase {
adModel1 = .init(adVerifications: [],
mp4MediaFiles: [],
vpaidMediaFiles: [],
clickthrough: nil,
adParameters: nil,
pixels: .init(),
id: "id1")
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: .init(),
id: "id1")

adModel2 = .init(adVerifications: [],
mp4MediaFiles: [],
vpaidMediaFiles: [],
skipOffset: .none,
clickthrough: nil,
adParameters: nil,
pixels: .init(),
Expand Down
1 change: 1 addition & 0 deletions sources/advertisements/VerifyBuldTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class VerifyBuldTests: XCTestCase {
vpaidMediaFiles: [Ad.VASTModel.VPAIDMediaFile(url: url,
scalable: false,
maintainAspectRatio: true)],
skipOffset: .none,
clickthrough: nil,
adParameters: "",
pixels: AdPixels(),
Expand Down

0 comments on commit 21199de

Please sign in to comment.