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

Commit

Permalink
Merge pull request #50 from VerizonAdPlatforms/OMSDK-2163/ad-request-…
Browse files Browse the repository at this point in the history
…detector

Ad engine request / ad request  detector
  • Loading branch information
VladyslavAnokhin committed Feb 1, 2019
2 parents 9b4cf49 + 7c60811 commit 6a5b837
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 1 deletion.
2 changes: 1 addition & 1 deletion PlayerCore
20 changes: 20 additions & 0 deletions VerizonVideoPartnerSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@
E241041C21C4078E00036290 /* StartVRMGroupProcessingControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E241041B21C4078E00036290 /* StartVRMGroupProcessingControllerTest.swift */; };
E257A9F521C927FF0016D35A /* VRMItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E257A9F421C927FF0016D35A /* VRMItemController.swift */; };
E257A9FB21C93F4A0016D35A /* VRMItemControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E257A9FA21C93F4A0016D35A /* VRMItemControllerTest.swift */; };
E2604391220379740034FC48 /* VRMRequestDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2604390220379740034FC48 /* VRMRequestDetector.swift */; };
E2604392220379740034FC48 /* VRMRequestDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2604390220379740034FC48 /* VRMRequestDetector.swift */; };
E2604397220379F10034FC48 /* VRMRequestDetectorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2604396220379F10034FC48 /* VRMRequestDetectorTest.swift */; };
E2629D07211228FA006ED117 /* TelemetryMetricsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2629D06211228FA006ED117 /* TelemetryMetricsTest.swift */; };
E2629D3C21147ECE006ED117 /* NoVpaidUrlFixture.json in Resources */ = {isa = PBXBuildFile; fileRef = E2629D3521147ECE006ED117 /* NoVpaidUrlFixture.json */; };
E287B08C21F884A900FC49AA /* VRMSelectFinalResultController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E287B08B21F884A900FC49AA /* VRMSelectFinalResultController.swift */; };
Expand All @@ -306,6 +309,9 @@
E2D649A8208A431D00152ADE /* VideoImpressionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D649A7208A431D00152ADE /* VideoImpressionTest.swift */; };
E2D64A5C2090E8F600152ADE /* VideoImpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E4F7032089020E00182CDF /* VideoImpression.swift */; };
E2E4F7042089020E00182CDF /* VideoImpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E4F7032089020E00182CDF /* VideoImpression.swift */; };
E2FD5AEC2203413E007EBE86 /* AdEngineRequestDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD5AEB2203413E007EBE86 /* AdEngineRequestDetector.swift */; };
E2FD5AED2203413E007EBE86 /* AdEngineRequestDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD5AEB2203413E007EBE86 /* AdEngineRequestDetector.swift */; };
E2FD5AEF2203414D007EBE86 /* AdEngineRequestDetectorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FD5AEE2203414D007EBE86 /* AdEngineRequestDetectorTest.swift */; };
E2FE09552200AC14005E91C0 /* MaxAdSearchTimeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE09542200AC14005E91C0 /* MaxAdSearchTimeController.swift */; };
E2FE09562200AC14005E91C0 /* MaxAdSearchTimeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE09542200AC14005E91C0 /* MaxAdSearchTimeController.swift */; };
E2FE095B2200AD01005E91C0 /* MaxAdSearchTimeControllerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FE095A2200AD01005E91C0 /* MaxAdSearchTimeControllerTest.swift */; };
Expand Down Expand Up @@ -647,6 +653,8 @@
E241041B21C4078E00036290 /* StartVRMGroupProcessingControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartVRMGroupProcessingControllerTest.swift; sourceTree = "<group>"; };
E257A9F421C927FF0016D35A /* VRMItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VRMItemController.swift; sourceTree = "<group>"; };
E257A9FA21C93F4A0016D35A /* VRMItemControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VRMItemControllerTest.swift; sourceTree = "<group>"; };
E2604390220379740034FC48 /* VRMRequestDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VRMRequestDetector.swift; sourceTree = "<group>"; };
E2604396220379F10034FC48 /* VRMRequestDetectorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VRMRequestDetectorTest.swift; sourceTree = "<group>"; };
E2629D06211228FA006ED117 /* TelemetryMetricsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TelemetryMetricsTest.swift; path = sources/telemetry/TelemetryMetricsTest.swift; sourceTree = "<group>"; };
E2629D3521147ECE006ED117 /* NoVpaidUrlFixture.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = NoVpaidUrlFixture.json; sourceTree = "<group>"; };
E287B08B21F884A900FC49AA /* VRMSelectFinalResultController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VRMSelectFinalResultController.swift; sourceTree = "<group>"; };
Expand All @@ -657,6 +665,8 @@
E2B0062521CD49EB00B72485 /* FetchVRMItemControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchVRMItemControllerTest.swift; sourceTree = "<group>"; };
E2D649A7208A431D00152ADE /* VideoImpressionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoImpressionTest.swift; sourceTree = "<group>"; };
E2E4F7032089020E00182CDF /* VideoImpression.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoImpression.swift; sourceTree = "<group>"; };
E2FD5AEB2203413E007EBE86 /* AdEngineRequestDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdEngineRequestDetector.swift; sourceTree = "<group>"; };
E2FD5AEE2203414D007EBE86 /* AdEngineRequestDetectorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdEngineRequestDetectorTest.swift; sourceTree = "<group>"; };
E2FE09542200AC14005E91C0 /* MaxAdSearchTimeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaxAdSearchTimeController.swift; sourceTree = "<group>"; };
E2FE095A2200AD01005E91C0 /* MaxAdSearchTimeControllerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaxAdSearchTimeControllerTest.swift; sourceTree = "<group>"; };
FE9409FF1F3DD56600A867CD /* IntentDetectorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentDetectorTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -980,6 +990,10 @@
children = (
50C99D512010DAE90041B013 /* VRMDetector.swift */,
508A597D2010F97B00641398 /* VRMDetectorTests.swift */,
E2FD5AEB2203413E007EBE86 /* AdEngineRequestDetector.swift */,
E2FD5AEE2203414D007EBE86 /* AdEngineRequestDetectorTest.swift */,
E2604390220379740034FC48 /* VRMRequestDetector.swift */,
E2604396220379F10034FC48 /* VRMRequestDetectorTest.swift */,
);
path = vrm;
sourceTree = "<group>";
Expand Down Expand Up @@ -1820,6 +1834,7 @@
50A11DCE1D59D7E000F4A068 /* ContextStartedDetector.swift in Sources */,
E241041A21C4075300036290 /* StartVRMGroupProcessingController.swift in Sources */,
50A11DD11D59D7E000F4A068 /* ExecuteOnce.swift in Sources */,
E2FD5AED2203413E007EBE86 /* AdEngineRequestDetector.swift in Sources */,
50A11DD31D59D7E000F4A068 /* VideoActionsDetector.swift in Sources */,
50A11DD41D59D7E000F4A068 /* XMLParser.swift in Sources */,
E287B0BB21FA097100FC49AA /* VPAIDAdCreativeController.swift in Sources */,
Expand All @@ -1829,6 +1844,7 @@
50A11DD81D59D7E000F4A068 /* PlaylistStatisticDetector.swift in Sources */,
50A5A5E71E79726E00C15E12 /* 3secPlaybackDetector.swift in Sources */,
50A11DDC1D59D7E000F4A068 /* VideoProviderParsing.swift in Sources */,
E2604392220379740034FC48 /* VRMRequestDetector.swift in Sources */,
50A11DDD1D59D7E000F4A068 /* Dictionary+ParseJSON.swift in Sources */,
E241041721C3FB3A00036290 /* VRMRequestController.swift in Sources */,
E23168AC212C4C9F00F5AD5B /* MaxShowTimeController.swift in Sources */,
Expand Down Expand Up @@ -1880,6 +1896,7 @@
E22B6A8521D14D1F00D480A0 /* ParseVRMItemController.swift in Sources */,
504CA7581C874A5D006D0ADF /* Player_VideoEvents.swift in Sources */,
DEB112361E30F0CE007E65BD /* Context.swift in Sources */,
E2604391220379740034FC48 /* VRMRequestDetector.swift in Sources */,
507053591DAE9700003C023A /* Memoise.swift in Sources */,
50D747751CE6235F00CB91D4 /* VRMRequest.swift in Sources */,
DE4C51E11C80D43200BFFB0B /* TrackingPixelsConnector.swift in Sources */,
Expand Down Expand Up @@ -1912,6 +1929,7 @@
DEAE91D81CAA830800C736D0 /* ApplyDecorator.swift in Sources */,
501AB1DE2028934A00BAFA9C /* AdErrorDetector.swift in Sources */,
50E5ADE91EE08A76004104D6 /* PlayerTracer.swift in Sources */,
E2FD5AEC2203413E007EBE86 /* AdEngineRequestDetector.swift in Sources */,
06419E2120EF7950007FE2F0 /* VPAIDProps.swift in Sources */,
DE4C51C51C8094FB00BFFB0B /* TrackingPixelsReporter.swift in Sources */,
501AB1E42029C69C00BAFA9C /* AdPlaybackCycleDetector.swift in Sources */,
Expand Down Expand Up @@ -1981,6 +1999,7 @@
067209EC21B6BF440086CDBE /* BufferingDetectorTests.swift in Sources */,
DE1FB2971CE48FAC00B99941 /* VRMProviderTests.swift in Sources */,
50C4602B1C80B791002AB8AB /* PlaylistStatisticDetectorTests.swift in Sources */,
E2604397220379F10034FC48 /* VRMRequestDetectorTest.swift in Sources */,
501AB1DB202892E800BAFA9C /* AdClickDetectorTests.swift in Sources */,
FEF072CB1F59A3D5006A0BDC /* PlayerDestructionTests.swift in Sources */,
E2FE095B2200AD01005E91C0 /* MaxAdSearchTimeControllerTest.swift in Sources */,
Expand All @@ -1993,6 +2012,7 @@
9A1469E621CE9549007315BA /* ActionComparator.swift in Sources */,
DE1685E71CE76A5D00492A90 /* VASTParserTests.swift in Sources */,
E241041621C3FAF400036290 /* VRMRequestControllerTest.swift in Sources */,
E2FD5AEF2203414D007EBE86 /* AdEngineRequestDetectorTest.swift in Sources */,
E231AA7721340100008C5B6A /* AdMaxShowTimeDetectorTest.swift in Sources */,
E2B0062821CD4A2B00B72485 /* FetchVRMItemControllerTest.swift in Sources */,
E22B6A8B21D14D2D00D480A0 /* ParseVRMItemControllerTest.swift in Sources */,
Expand Down
10 changes: 10 additions & 0 deletions sources/advertisements/AdMetrics.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018, Oath Inc.
// Licensed under the terms of the MIT License. See LICENSE.md file in project root for terms.
import Foundation
import PlayerCore

enum Ad { }

Expand Down Expand Up @@ -74,4 +75,13 @@ extension Ad.Metrics.Info {
self.name = metaInfo.name
self.cpm = metaInfo.cpm
}

init(metaInfo: VRMCore.Item.MetaInfo) {
self.engineType = metaInfo.engineType
self.ruleId = metaInfo.ruleId
self.ruleCompanyId = metaInfo.ruleCompanyId
self.vendor = metaInfo.vendor
self.name = metaInfo.name
self.cpm = metaInfo.cpm
}
}
47 changes: 47 additions & 0 deletions sources/metrics/detectors/vrm/AdEngineRequestDetector.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2019, Oath Inc.
// Licensed under the terms of the MIT License. See LICENSE.md file in project root for terms.

import Foundation
import PlayerCore

extension Detectors {

final class AdEngineRequestDetector {

struct Result {
let adInfo: Ad.Metrics.Info
let transactionId: String?
}

private var processedCandidates = Set<ScheduledVRMItems.Candidate>()

func process(state: PlayerCore.State) -> [Result] {
return process(transactionId: state.vrmResponse?.transactionId,
scheduledItems: state.vrmScheduledItems.items)
}

func process(transactionId: String?,
scheduledItems: [VRMCore.Item: Set<ScheduledVRMItems.Candidate>]) -> [Result] {
guard scheduledItems.isEmpty == false else { return [] }

struct NormalizedScheduledItem {
let item: VRMCore.Item
let candidate: ScheduledVRMItems.Candidate
}

return scheduledItems
.filter { _, candidatesSet in
candidatesSet.isSubset(of: processedCandidates) == false
}.reduce(into: []) { result, pair in
return pair.value.forEach { candidate in
result.append(NormalizedScheduledItem(item: pair.key, candidate: candidate))
}
}.compactMap { normalized in
processedCandidates.insert(normalized.candidate)
return Result(adInfo: .init(metaInfo: normalized.item.metaInfo), transactionId: transactionId)
}
}
}

}

83 changes: 83 additions & 0 deletions sources/metrics/detectors/vrm/AdEngineRequestDetectorTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2018, Oath Inc.
// Licensed under the terms of the MIT License. See LICENSE.md file in project root for terms.

import XCTest
@testable import VerizonVideoPartnerSDK
@testable import PlayerCore

class AdEngineRequestDetectorTest: XCTestCase {

let firstCandidate = ScheduledVRMItems.Candidate(source: .vast(""))
let secondCandidate = ScheduledVRMItems.Candidate(source: .vast(""))

var firstMetainfo: VRMCore.Item.MetaInfo!
var secondMetainfo: VRMCore.Item.MetaInfo!
var firstItem: VRMCore.Item!
var secondItem: VRMCore.Item!
var detector: Detectors.AdEngineRequestDetector!

override func setUp() {
super.setUp()
detector = Detectors.AdEngineRequestDetector()
firstMetainfo = VRMCore.Item.MetaInfo(engineType: "engineType1",
ruleId: "ruleId1",
ruleCompanyId: "ruleCompanyId1",
vendor: "vendor1",
name: "name1",
cpm: "cpm1")
secondMetainfo = VRMCore.Item.MetaInfo(engineType: "engineType2",
ruleId: "ruleId2",
ruleCompanyId: "ruleCompanyId2",
vendor: "vendor2",
name: "name2",
cpm: "cpm2")
firstItem = VRMCore.Item(source: .vast(""), metaInfo: firstMetainfo)
secondItem = VRMCore.Item(source: .vast(""), metaInfo: secondMetainfo)
}

func testEmptyDetect() {
let result = detector.process(transactionId: "", scheduledItems: [:])
XCTAssertTrue(result.isEmpty)
}

func testCorrectDetection() {
let queue: [VRMCore.Item: Set<ScheduledVRMItems.Candidate>] = [firstItem: Set([firstCandidate])]
var result = detector.process(transactionId: "", scheduledItems: queue)

XCTAssertEqual(result.count, 1)
XCTAssertEqual(result[0].adInfo.engineType, firstMetainfo.engineType)
XCTAssertEqual(result[0].adInfo.ruleId, firstMetainfo.ruleId)
XCTAssertEqual(result[0].adInfo.ruleCompanyId, firstMetainfo.ruleCompanyId)
XCTAssertEqual(result[0].adInfo.vendor, firstMetainfo.vendor)
XCTAssertEqual(result[0].adInfo.name, firstMetainfo.name)
XCTAssertEqual(result[0].adInfo.cpm, firstMetainfo.cpm)
}

func testDoubleDetectSameCandidate() {
let queue: [VRMCore.Item: Set<ScheduledVRMItems.Candidate>] = [firstItem: Set([firstCandidate])]
var result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertEqual(result.count, 1)

result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertTrue(result.isEmpty)
}

func testDetectingTwoCandidates() {
let queue: [VRMCore.Item: Set<ScheduledVRMItems.Candidate>] = [firstItem: Set([firstCandidate, secondCandidate])]
var result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertEqual(result.count, 2)

result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertTrue(result.isEmpty)
}

func testDetectingTwoItems() {
let queue: [VRMCore.Item: Set<ScheduledVRMItems.Candidate>] = [firstItem: Set([firstCandidate]),
secondItem: Set([secondCandidate])]
var result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertEqual(result.count, 2)

result = detector.process(transactionId: "", scheduledItems: queue)
XCTAssertTrue(result.isEmpty)
}
}
28 changes: 28 additions & 0 deletions sources/metrics/detectors/vrm/VRMRequestDetector.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019, Oath Inc.
// Licensed under the terms of the MIT License. See LICENSE.md file in project root for terms.

import Foundation
import PlayerCore

extension Detectors {
final class VRMRequestDetector {
struct Result {
let transactionId: String?
}

private var trackedRequests = Set<UUID>()

func process(with state: PlayerCore.State) -> Result? {
return process(with: state.vrmRequestStatus.request?.id,
transactionId: state.vrmResponse?.transactionId)
}

func process(with requestId: UUID?, transactionId: String?) -> Result? {
guard let requestId = requestId,
trackedRequests.contains(requestId) == false else { return nil }

trackedRequests.insert(requestId)
return Result(transactionId: transactionId)
}
}
}
30 changes: 30 additions & 0 deletions sources/metrics/detectors/vrm/VRMRequestDetectorTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2018, Oath Inc.
// Licensed under the terms of the MIT License. See LICENSE.md file in project root for terms.

import XCTest
@testable import VerizonVideoPartnerSDK
@testable import PlayerCore

class VRMRequestDetectorTest: XCTestCase {

func testDetectSameRequest() {
let uuid = UUID()
let sut = Detectors.VRMRequestDetector()

var result = sut.process(with: uuid, transactionId: "id")
XCTAssertEqual(result?.transactionId, "id")

result = sut.process(with: uuid, transactionId: "id")
XCTAssertNil(result)
}

func testDetectDiffRequests() {
let sut = Detectors.VRMRequestDetector()

var result = sut.process(with: UUID(), transactionId: "id1")
XCTAssertEqual(result?.transactionId, "id1")

result = sut.process(with: UUID(), transactionId: "id2")
XCTAssertEqual(result?.transactionId, "id2")
}
}
3 changes: 3 additions & 0 deletions sources/metrics/tracking pixels/TrackingPixelsConnector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ extension TrackingPixels {
let videoImpressionDetector = Detectors.VideoImpression()

let vrmDetector = Detectors.VRMDetector()
let adRequestDetector = Detectors.VRMRequestDetector()
let adEngineRequestDetector = Detectors.AdEngineRequestDetector()

let adVideoLoadingDetector = Detectors.VideoLoading()
let adQuartileDetector = Detectors.Quartile()
let adUserActionsDetector = Detectors.UserActions()
Expand Down
Loading

0 comments on commit 6a5b837

Please sign in to comment.