~ubuntu-branches/ubuntu/saucy/emscripten/saucy-proposed

« back to all changes in this revision

Viewing changes to tools/reproduceriter.js

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
var Recorder = (function() {
 
3
  var recorder;
 
4
  var init = 'reproduce=';
 
5
  var initLocation = window.location.search.indexOf(init);
 
6
  var replaying = initLocation >= 0;
 
7
  var raf = window['requestAnimationFrame'] ||
 
8
            window['mozRequestAnimationFrame'] ||
 
9
            window['webkitRequestAnimationFrame'] ||
 
10
            window['msRequestAnimationFrame'] ||
 
11
            window['oRequestAnimationFrame'];
 
12
  if (!replaying) {
 
13
    // Prepare to record
 
14
    recorder = {};
 
15
    // Start
 
16
    recorder.frameCounter = 0; // the frame counter is used to know when to replay events
 
17
    recorder.start = function() {
 
18
      alert("Starting recording! Don't forget to Recorder.finish() afterwards!");
 
19
      function count() {
 
20
        recorder.frameCounter++;
 
21
        raf(count);
 
22
      }
 
23
      count();
 
24
      recorder.started = true;
 
25
    };
 
26
    // Math.random
 
27
    recorder.randoms = [];
 
28
    recorder.random = Math.random;
 
29
    Math.random = function() {
 
30
      var ret = recorder.random();
 
31
      recorder.randoms.push(ret);
 
32
      return ret;
 
33
    };
 
34
    // Date.now, performance.now
 
35
    recorder.dnows = [];
 
36
    recorder.dnow = Date.now;
 
37
    Date.now = function() {
 
38
      var ret = recorder.dnow();
 
39
      recorder.dnows.push(ret);
 
40
      return ret;
 
41
    };
 
42
    recorder.pnows = [];
 
43
    var pnow = performance.now || performance.webkitNow || performance.mozNow || performance.oNow || performance.msNow;
 
44
    recorder.pnow = function() { return pnow.call(performance) };
 
45
    performance.now = function() {
 
46
      var ret = recorder.pnow();
 
47
      recorder.pnows.push(ret);
 
48
      return ret;
 
49
    };
 
50
    // Events
 
51
    recorder.devents = []; // document events
 
52
    recorder.onEvent = function(which, callback) {
 
53
      document['on' + which] = function(event) {
 
54
        if (!recorder.started) return true;
 
55
        event.frameCounter = recorder.frameCounter;
 
56
        recorder.devents.push(event);
 
57
        return callback(event); // XXX do we need to record the return value?
 
58
      };
 
59
    };
 
60
    recorder.tevents = []; // custom-target events. Currently we assume a single such custom target (aside from document), e.g., a canvas for the game.
 
61
    recorder.addListener = function(target, which, callback, arg) {
 
62
      target.addEventListener(which, function(event) {
 
63
        if (!recorder.started) return true;
 
64
        event.frameCounter = recorder.frameCounter;
 
65
        recorder.tevents.push(event);
 
66
        return callback(event); // XXX do we need to record the return value?
 
67
      }, arg);
 
68
    };
 
69
    // Finish
 
70
    recorder.finish = function() {
 
71
      // Reorder data because pop() is faster than shift()
 
72
      recorder.randoms.reverse();
 
73
      recorder.dnows.reverse();
 
74
      recorder.pnows.reverse();
 
75
      recorder.devents.reverse();
 
76
      recorder.tevents.reverse();
 
77
      // Make JSON.stringify work on data from native event objects (and only store relevant ones)
 
78
      var importantProperties = {
 
79
        type: 1,
 
80
        movementX: 1, mozMovementX: 1, webkitMovementX: 1,
 
81
        movementY: 1, mozMovementY: 1, webkitMovementY: 1,
 
82
        detail: 1,
 
83
        wheelDelta: 1,
 
84
        pageX: 1,
 
85
        pageY: 1,
 
86
        button: 1,
 
87
        keyCode: 1,
 
88
        frameCounter: 1
 
89
      };
 
90
      function importantize(event) {
 
91
        var ret = {};
 
92
        for (var prop in importantProperties) {
 
93
          if (prop in event) {
 
94
            ret[prop] = event[prop];
 
95
          }
 
96
        }
 
97
        return ret;
 
98
      }
 
99
      recorder.devents = recorder.devents.map(importantize);
 
100
      recorder.tevents = recorder.tevents.map(importantize);
 
101
      // Write out
 
102
      alert('Writing out data, remember to save!');
 
103
      setTimeout(function() {
 
104
        document.open();
 
105
        document.write(JSON.stringify(recorder));
 
106
        document.close();
 
107
      }, 0);
 
108
      return '.';
 
109
    };
 
110
  } else {
 
111
    // Load recording
 
112
    var dataPath = window.location.search.substring(initLocation + init.length);
 
113
    var baseURL = window.location.toString().replace('://', 'cheez999').split('?')[0].split('/').slice(0, -1).join('/').replace('cheez999', '://');
 
114
    if (baseURL[baseURL.length-1] != '/') baseURL += '/';
 
115
    var path = baseURL + dataPath;
 
116
    alert('Loading replay from ' + path);
 
117
    var request = new XMLHttpRequest();
 
118
    request.open('GET', path, false);
 
119
    request.send();
 
120
    var raw = request.responseText;
 
121
    raw = raw.substring(raw.indexOf('{'), raw.lastIndexOf('}')+1); // remove <html> etc
 
122
    recorder = JSON.parse(raw);
 
123
    // prepare to replay
 
124
    // Start
 
125
    recorder.frameCounter = 0; // the frame counter is used to know when to replay events
 
126
    recorder.start = function() {
 
127
      function count() {
 
128
        recorder.frameCounter++;
 
129
        raf(count);
 
130
        // replay relevant events for this frame
 
131
        while (recorder.devents.length && recorder.devents[recorder.devents.length-1].frameCounter <= recorder.frameCounter) {
 
132
          var event = recorder.devents.pop();
 
133
          recorder['on' + event.type](event);
 
134
        }
 
135
        while (recorder.tevents.length && recorder.tevents[recorder.tevents.length-1].frameCounter <= recorder.frameCounter) {
 
136
          var event = recorder.tevents.pop();
 
137
          recorder['event' + event.type](event);
 
138
        }
 
139
      }
 
140
      count();
 
141
    };
 
142
    // Math.random
 
143
    recorder.random = Math.random;
 
144
    Math.random = function() {
 
145
      if (recorder.randoms.length > 0) {
 
146
        return recorder.randoms.pop();
 
147
      } else {
 
148
        recorder.finish();
 
149
        throw 'consuming too many random values!';
 
150
      }
 
151
    };
 
152
    // Date.now, performance.now
 
153
    recorder.dnow = Date.now;
 
154
    Date.now = function() {
 
155
      if (recorder.dnows.length > 0) {
 
156
        return recorder.dnows.pop();
 
157
      } else {
 
158
        recorder.finish();
 
159
        throw 'consuming too many Date.now values!';
 
160
      }
 
161
    };
 
162
    var pnow = performance.now || performance.webkitNow || performance.mozNow || performance.oNow || performance.msNow;
 
163
    recorder.pnow = function() { return pnow.call(performance) };
 
164
    performance.now = function() {
 
165
      if (recorder.pnows.length > 0) {
 
166
        return recorder.pnows.pop();
 
167
      } else {
 
168
        recorder.finish();
 
169
        throw 'consuming too many performance.now values!';
 
170
      }
 
171
    };
 
172
    // Events
 
173
    recorder.onEvent = function(which, callback) {
 
174
      recorder['on' + which] = callback;
 
175
    };
 
176
    recorder.eventCallbacks = {};
 
177
    recorder.addListener = function(target, which, callback, arg) {
 
178
      recorder['event' + which] = callback;
 
179
    };
 
180
    recorder.onFinish = [];
 
181
    // Benchmarking hooks - emscripten specific
 
182
    setTimeout(function() {
 
183
      var totalTime = 0;
 
184
      var totalSquared = 0;
 
185
      var iterations = 0;
 
186
      var maxTime = 0;
 
187
      var curr = 0;
 
188
      Module.preMainLoop = function() {
 
189
        curr = recorder.pnow();
 
190
      }
 
191
      Module.postMainLoop = function() {
 
192
        var time = recorder.pnow() - curr;
 
193
        totalTime += time;
 
194
        totalSquared += time*time;
 
195
        maxTime = Math.max(maxTime, time);
 
196
        iterations++;
 
197
      };
 
198
      recorder.onFinish.push(function() {
 
199
        var mean = totalTime / iterations;
 
200
        var meanSquared = totalSquared / iterations;
 
201
        console.log('mean frame   : ' + mean + ' ms');
 
202
        console.log('frame std dev: ' + Math.sqrt(meanSquared - (mean*mean)) + ' ms');
 
203
        console.log('max frame    : ' + maxTime + ' ms');
 
204
      });    
 
205
    });
 
206
    // Finish
 
207
    recorder.finish = function() {
 
208
      recorder.onFinish.forEach(function(finish) {
 
209
        finish();
 
210
      });
 
211
    };
 
212
  }
 
213
  recorder.replaying = replaying;
 
214
  return recorder;
 
215
})();
 
216