<commit_before>/*
The MIT License (MIT)

Copyright (c) 2014 Gregory McGee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

angular.module('gm.datepickerMultiSelect', ['ui.bootstrap'])
.config(function($provide) {
	$provide.decorator('daypickerDirective', function($delegate) {
		var directive = $delegate[0];

		/* Override compile */
		var link = directive.link;

		directive.compile = function() {
			return function(scope, element, attrs, ctrl) {
				link.apply(this, arguments);

				var selectedDates = [];
				var alreadyUpdated;

				/* Called when multiSelect model is updated */
				scope.$on('update', function(event, newDates) {
					selectedDates = newDates;
					update();
				});

				/* Get dates pushed into multiSelect array before Datepicker is ready */
				scope.$emit('requestSelectedDates');

				/**
				 * Fires when date is selected or when month is changed.
				 * Fires after multiSelect model updates, so check to
				 * see if update was already called this cycle.
				 **/
				scope.$parent.$watch('activeDateId', function() {
					if(!alreadyUpdated)
						update();
					alreadyUpdated = false;
				});

				function update() {
					angular.forEach(scope.rows, function(row) {
						angular.forEach(row, function(day) {
							day.selected = selectedDates.indexOf(day.date.setHours(0, 0, 0, 0)) > -1
						});
					});
					alreadyUpdated = true;
				}
			}
		}

		return $delegate;
	});
})
.directive('multiSelect', function() {
	return {
		require: ['datepicker', 'ngModel'],
		link: function(scope, elem, attrs, ctrls) {
			var selectedDates = scope.$eval(attrs.multiSelect);

			/* Called when directive is compiled */
			scope.$on('requestSelectedDates', function() {
				scope.$broadcast('update', selectedDates);
			});

			scope.$watchCollection(attrs.multiSelect, function(newVal) {
				scope.$broadcast('update', selectedDates);
			});

			scope.$watch(attrs.ngModel, function(newVal, oldVal) {
				if(!newVal) return;

				var dateVal = newVal.getTime();

				if(selectedDates.indexOf(dateVal) < 0) {
					selectedDates.push(dateVal);
				} else {
					selectedDates.splice(selectedDates.indexOf(dateVal), 1);
				}
			});
		}
	}
});
<commit_msg>Address issue in PR #3<commit_after>/*
The MIT License (MIT)

Copyright (c) 2014 Gregory McGee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

angular.module('gm.datepickerMultiSelect', ['ui.bootstrap'])
.config(function($provide) {
	$provide.decorator('daypickerDirective', function($delegate) {
		var directive = $delegate[0];

		/* Override compile */
		var link = directive.link;

		directive.compile = function() {
			return function(scope, element, attrs, ctrl) {
				link.apply(this, arguments);

				var selectedDates = [];
				var alreadyUpdated;

				/* Called when multiSelect model is updated */
				scope.$on('update', function(event, newDates) {
					selectedDates = newDates;
					update();
				});

				/* Get dates pushed into multiSelect array before Datepicker is ready */
				scope.$emit('requestSelectedDates');

				/**
				 * Fires when date is selected or when month is changed.
				 * Fires after multiSelect model updates, so check to
				 * see if update was already called this cycle.
				 **/
				scope.$parent.$watch('activeDateId', function() {
					if(!alreadyUpdated)
						update();
					alreadyUpdated = false;
				});

				function update() {
					angular.forEach(scope.rows, function(row) {
						angular.forEach(row, function(day) {
							day.selected = selectedDates.indexOf(day.date.setHours(0, 0, 0, 0)) > -1
						});
					});
					alreadyUpdated = true;
				}
			}
		}

		return $delegate;
	});
})
.directive('multiSelect', function() {
	return {
		require: ['datepicker', 'ngModel'],
		link: function(scope, elem, attrs, ctrls) {
			var selectedDates;

			/* Called when directive is compiled */
			scope.$on('requestSelectedDates', function() {
				scope.$broadcast('update', selectedDates);
			});

			scope.$watchCollection(attrs.multiSelect, function(newVal) {
				selectedDates = newVal;
				scope.$broadcast('update', selectedDates);
			});

			scope.$watch(attrs.ngModel, function(newVal, oldVal) {
				if(!newVal) return;

				var dateVal = newVal.getTime();

				if(selectedDates.indexOf(dateVal) < 0) {
					selectedDates.push(dateVal);
				} else {
					selectedDates.splice(selectedDates.indexOf(dateVal), 1);
				}
			});
		}
	}
});
<|endoftext|>


<commit_before>import {deepAccess, deepSetValue, getBidIdParameter, getUniqueIdentifierStr, logWarn, mergeDeep} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {config} from '../src/config.js';
import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
import {Renderer} from '../src/Renderer.js';
import {hasPurpose1Consent} from '../src/utils/gpdr.js';
import {ortbConverter} from '../libraries/ortbConverter/converter.js';
import {loadExternalScript} from '../src/adloader.js';

const BIDDER_CODE = 'improvedigital';
const CREATIVE_TTL = 300;

const AD_SERVER_BASE_URL = 'https://ad.360yield.com';
const BASIC_ADS_BASE_URL = 'https://ad.360yield-basic.com';
const PB_ENDPOINT = 'pb';
const EXTEND_URL = 'https://pbs.360yield.com/openrtb2/auction';
const IFRAME_SYNC_URL = 'https://hb.360yield.com/prebid-universal-creative/load-cookie.html';

const VIDEO_PARAMS = {
  DEFAULT_MIMES: ['video/mp4'],
  PLACEMENT_TYPE: {
    INSTREAM: 1,
    OUTSTREAM: 3,
  }
};

export const spec = {
  code: BIDDER_CODE,
  gvlid: 253,
  aliases: ['id'],
  supportedMediaTypes: [BANNER, NATIVE, VIDEO],
  syncStore: { extendMode: false, placementId: null },

  /**
   * Determines whether or not the given bid request is valid.
   *
   * @param {object} bid The bid to validate.
   * @return boolean True if this is a valid bid, and false otherwise.
   */
  isBidRequestValid(bid) {
    return !!(bid && bid.params && (bid.params.placementId || (bid.params.placementKey && bid.params.publisherId)));
  },

  /**
   * Make a server request from the list of BidRequests.
   *
   * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server.
   * @param bidderRequest
   * @return ServerRequest Info describing the request to the server.
   */
  buildRequests(bidRequests, bidderRequest) {
    // Save a placement id to send it to the ad server when fetching the user syncs
    this.syncStore.placementId = this.syncStore.placementId || bidRequests[0].params.placementId;
    return ID_REQUEST.buildServerRequests(bidRequests, bidderRequest);
  },

  /**
   * Unpack the response from the server into a list of bids.
   *
   * @param {*} serverResponse A successful response from the server.
   * @param bidderRequest
   * @return {Bid[]} An array of bids which were nested inside the server.
   */
  interpretResponse(serverResponse, { ortbRequest }) {
    return CONVERTER.fromORTB({request: ortbRequest, response: serverResponse.body}).bids;
  },

  /**
   * Register the user sync pixels which should be dropped after the auction.
   *
   * @param {SyncOptions} syncOptions Which user syncs are allowed?
   * @param {ServerResponse[]} serverResponses List of server's responses.
   * @return {UserSync[]} The user syncs which should be dropped.
   */
  getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
    if (config.getConfig('coppa') === true || !hasPurpose1Consent(gdprConsent)) {
      return [];
    }

    const bidders = new Set();
    if (this.syncStore.extendMode && serverResponses) {
      serverResponses.forEach(response => {
        if (!response?.body?.ext?.responsetimemillis) return;
        Object.keys(response.body.ext.responsetimemillis).forEach(b => bidders.add(b))
      })
    }

    const syncs = [];
    if ((this.syncStore.extendMode || !syncOptions.pixelEnabled) && syncOptions.iframeEnabled) {
      const { gdprApplies, consentString } = gdprConsent || {};
      syncs.push({
        type: 'iframe',
        url: IFRAME_SYNC_URL +
          `?placement_id=${this.syncStore.placementId}` +
          (this.syncStore.extendMode ? '&pbs=1' : '') +
          (typeof gdprApplies === 'boolean' ? `&gdpr=${Number(gdprApplies)}` : '') +
          (consentString ? `&gdpr_consent=${consentString}` : '') +
          (uspConsent ? `&us_privacy=${encodeURIComponent(uspConsent)}` : '') +
          (bidders.size ? `&bidders=${[...bidders].join(',')}` : '')
      });
    } else if (syncOptions.pixelEnabled) {
      serverResponses.forEach(response => {
        const syncArr = deepAccess(response, `body.ext.${BIDDER_CODE}.sync`, []);
        syncArr.forEach(url => {
          if (!syncs.some(sync => sync.url === url)) {
            syncs.push({ type: 'image', url });
          }
        });
      });
    }

    return syncs;
  }
};

registerBidder(spec);

export const CONVERTER = ortbConverter({
  context: {
    ttl: CREATIVE_TTL,
    nativeRequest: {
      eventtrackers: [
        {event: 1, methods: [1, 2]},
      ]
    }
  },
  imp(buildImp, bidRequest, context) {
    const imp = buildImp(bidRequest, context);
    imp.secure = Number(window.location.protocol === 'https:');
    if (!imp.bidfloor && bidRequest.params.bidFloor) {
      imp.bidfloor = bidRequest.params.bidFloor;
      imp.bidfloorcur = getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || 'USD'
    }
    const bidderParamsPath = context.extendMode ? 'ext.prebid.bidder.improvedigital' : 'ext.bidder';
    const placementId = bidRequest.params.placementId;
    if (placementId) {
      deepSetValue(imp, `${bidderParamsPath}.placementId`, placementId);
      if (context.extendMode) {
        deepSetValue(imp, 'ext.prebid.storedrequest.id', '' + placementId);
      }
    } else {
      deepSetValue(imp, `${bidderParamsPath}.publisherId`, getBidIdParameter('publisherId', bidRequest.params));
      deepSetValue(imp, `${bidderParamsPath}.placementKey`, getBidIdParameter('placementKey', bidRequest.params));
    }
    deepSetValue(imp, `${bidderParamsPath}.keyValues`, getBidIdParameter('keyValues', bidRequest.params) || undefined);

    return imp;
  },
  request(buildRequest, imps, bidderRequest, context) {
    const request = buildRequest(imps, bidderRequest, context);
    mergeDeep(request, {
      id: getUniqueIdentifierStr(),
      source: {
        // TODO: once https://github.com/prebid/Prebid.js/issues/8573 is resolved, this should be handled by the base ortbConverter logic
        tid: context.bidRequests[0].transactionId,
      },
      ext: {
        improvedigital: {
          sdk: {
            name: 'pbjs',
            version: '$prebid.version$',
          }
        }
      },
    });
    return request;
  },
  bidResponse(buildBidResponse, bid, context) {
    if (!bid.adm || !bid.price || bid.hasOwnProperty('errorCode')) {
      return;
    }
    const {bidRequest} = context;
    context.mediaType = (() => {
      const requestMediaTypes = Object.keys(bidRequest.mediaTypes);
      if (requestMediaTypes.length === 1) return requestMediaTypes[0];
      // Detect media type for multi-format response
      if (bid.adm.search(/^(<\?xml|<vast)/i) !== -1) {
        return VIDEO;
      } else if (bid.adm[0] === '{') {
        return NATIVE;
      } else {
        return BANNER;
      }
    })();
    const bidResponse = buildBidResponse(bid, context);
    const idExt = deepAccess(bid, `ext.${BIDDER_CODE}`, {});
    Object.assign(bidResponse, {
      dealId: (typeof idExt.buying_type === 'string' && idExt.buying_type !== 'rtb') ? idExt.line_item_id : undefined,
      netRevenue: idExt.is_net || false,
    })
    if (bidResponse.mediaType === VIDEO && ID_REQUEST.isOutstreamVideo(bidRequest)) {
      Object.assign(bidResponse, {
        adResponse: { content: bidResponse.vastXml },
        renderer: ID_OUTSTREAM.createRenderer(bidRequest)
      })
    }
    ID_RAZR.forwardBid({bidRequest, bid: bidResponse});
    return bidResponse;
  },
  overrides: {
    imp: {
      banner(fillImpBanner, imp, bidRequest, context) {
        // override to disregard banner.sizes if usePrebidSizes is not set
        if (!bidRequest.mediaTypes[BANNER]) return;
        if (config.getConfig('improvedigital.usePrebidSizes') !== true) {
          const banner = Object.assign({}, bidRequest.mediaTypes[BANNER], {sizes: null});
          bidRequest = {...bidRequest, mediaTypes: {[BANNER]: banner}}
        }
        fillImpBanner(imp, bidRequest, context);
      },
      video(fillImpVideo, imp, bidRequest, context) {
        // override to use video params from both mediaTypes.video and bidRequest.params.video
        if (!bidRequest.mediaTypes[VIDEO]) return;
        const video = Object.assign(
          {mimes: VIDEO_PARAMS.DEFAULT_MIMES},
          bidRequest.mediaTypes[VIDEO],
          bidRequest.params?.video
        )
        fillImpVideo(
          imp,
          {...bidRequest, mediaTypes: {[VIDEO]: video}},
          context
        );
        deepSetValue(imp, 'ext.is_rewarded_inventory', (video.rewarded === 1 || deepAccess(video, 'ext.rewarded') === 1) || undefined);
        if (!imp.video.placement && ID_REQUEST.isOutstreamVideo(bidRequest)) {
          // fillImpVideo will have already set placement = 1 for instream
          imp.video.placement = VIDEO_PARAMS.PLACEMENT_TYPE.OUTSTREAM;
        }
      }
    },
    request: {
      gdprAddtlConsent(setAddtlConsent, ortbRequest, bidderRequest) {
        const additionalConsent = bidderRequest?.gdprConsent?.addtlConsent;
        if (!additionalConsent) {
          return;
        }

        if (spec.syncStore.extendMode) {
          return setAddtlConsent(ortbRequest, bidderRequest);
        }

        // Additional Consent String
        if (additionalConsent && additionalConsent.indexOf('~') !== -1) {
          // Google Ad Tech Provider IDs
          const atpIds = additionalConsent.substring(additionalConsent.indexOf('~') + 1);
          if (atpIds) {
            deepSetValue(
              ortbRequest,
              'user.ext.consented_providers_settings.consented_providers',
              atpIds.split('.').map(id => parseInt(id, 10))
            );
          }
        }
      }
    }
  }
})

const ID_REQUEST = {
  buildServerRequests(bidRequests, bidderRequest) {
    const globalExtendMode = config.getConfig('improvedigital.extend') === true;
    const requests = [];
    const singleRequestMode = config.getConfig('improvedigital.singleRequest') === true;

    const extendBids = [];
    const adServerBids = [];

    function adServerUrl(extendMode, publisherId) {
      if (extendMode) {
        return EXTEND_URL;
      }

      const urlSegments = [];
      urlSegments.push(hasPurpose1Consent(bidderRequest?.gdprConsent) ? AD_SERVER_BASE_URL : BASIC_ADS_BASE_URL)
      if (publisherId) {
        urlSegments.push(publisherId)
      }
      urlSegments.push(PB_ENDPOINT)

      return urlSegments.join('/');
    }

    function formatRequest(bidRequests, {transactionId, publisherId}, extendMode) {
      const ortbRequest = CONVERTER.toORTB({bidRequests, bidderRequest, context: {extendMode}});
      return {
        method: 'POST',
        url: adServerUrl(extendMode, publisherId),
        data: JSON.stringify(ortbRequest),
        ortbRequest,
        bidderRequest
      }
    }

    let publisherId = null;
    bidRequests.map((bidRequest) => {
      const bidParams = bidRequest.params;
      const extendModeEnabled = this.isExtendModeEnabled(globalExtendMode, bidParams);
      if (singleRequestMode) {
        if (!publisherId) {
          publisherId = bidParams?.publisherId;
        } else if (publisherId && bidParams?.publisherId && publisherId !== bidParams?.publisherId) {
          throw new Error(`All Improve Digital placements in a single call must have the same publisherId. Please check your 'params.publisherId' or turn off the single request mode.`);
        }
        extendModeEnabled ? extendBids.push(bidRequest) : adServerBids.push(bidRequest);
      } else {
        requests.push(formatRequest([bidRequest], {transactionId: bidRequest.transactionId, publisherId: bidParams?.publisherId}, extendModeEnabled));
      }
    });

    if (!singleRequestMode) {
      return requests;
    }
    const requestOptions = {
      transactionId: bidderRequest.auctionId,
      publisherId,
    }
    // In the single request mode, split imps between those going to the ad server and those going to extend server
    if (extendBids.length) {
      requests.push(formatRequest(extendBids, requestOptions, true));
    }
    if (adServerBids.length) {
      requests.push(formatRequest(adServerBids, requestOptions, false));
    }

    return requests;
  },

  isExtendModeEnabled(globalExtendMode, bidParams) {
    const extendMode = typeof bidParams.extend === 'boolean' ? bidParams.extend : globalExtendMode;
    if (extendMode && !spec.syncStore.extendMode) {
      spec.syncStore.extendMode = true;
    }
    return extendMode;
  },

  isOutstreamVideo(bidRequest) {
    return deepAccess(bidRequest, 'mediaTypes.video.context') === 'outstream';
  },

};

const ID_OUTSTREAM = {
  RENDERER_URL: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js',
  createRenderer(bidRequest) {
    const renderer = Renderer.install({
      id: bidRequest.adUnitCode,
      url: this.RENDERER_URL,
      config: deepAccess(bidRequest, 'renderer.options'),
      adUnitCode: bidRequest.adUnitCode
    });
    try {
      renderer.setRender(this.render);
    } catch (err) {
      logWarn('Prebid Error calling setRender on renderer', err);
    }
    return renderer;
  },

  render(bid) {
    bid.renderer.push(() => {
      window.ANOutstreamVideo.renderAd({
        sizes: [bid.width, bid.height],
        targetId: bid.adUnitCode,
        adResponse: bid.adResponse,
        rendererOptions: bid.renderer.getConfig()
      }, ID_OUTSTREAM.handleRendererEvents.bind(null, bid));
    });
  },

  handleRendererEvents(bid, id, eventName) {
    bid.renderer.handleVideoEvent({ id, eventName });
  },
};

const ID_RAZR = {
  RENDERER_URL: 'https://cdn.360yield.com/razr/tag.js',

  forwardBid({bidRequest, bid}) {
    if (bid.mediaType !== BANNER) {
      return;
    }

    const cfg = {
      prebid: {
        bidRequest,
        bid
      }
    };

    const cfgStr = JSON.stringify(cfg).replace(/<\/script>/g, '\\x3C/script>');
    const s = `<script>window.__razr_config = ${cfgStr};</script>`;
    bid.ad = bid.ad.replace(/<body[^>]*>/, match => match + s);

    this.installListener();
  },

  installListener() {
    if (this._listenerInstalled) {
      return;
    }

    window.addEventListener('message', function(e) {
      const data = e.data?.razr?.load;
      if (!data) {
        return;
      }

      if (e.source) {
        data.source = e.source;
        if (data.id) {
          e.source.postMessage({
            razr: {
              id: data.id
            }
          }, '*');
        }
      }

      const ns = window.razr = window.razr || {};
      ns.q = ns.q || [];
      ns.q.push(data);

      if (!ns.loaded) {
        loadExternalScript(ID_RAZR.RENDERER_URL, BIDDER_CODE);
      }
    });

    this._listenerInstalled = true;
  }
};
<commit_msg>Minor changes<commit_after>import {deepAccess, deepSetValue, getBidIdParameter, getUniqueIdentifierStr, logWarn, mergeDeep} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {config} from '../src/config.js';
import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
import {Renderer} from '../src/Renderer.js';
import {hasPurpose1Consent} from '../src/utils/gpdr.js';
import {ortbConverter} from '../libraries/ortbConverter/converter.js';
import {loadExternalScript} from '../src/adloader.js';

const BIDDER_CODE = 'improvedigital';
const CREATIVE_TTL = 300;

const AD_SERVER_BASE_URL = 'https://ad.360yield.com';
const BASIC_ADS_BASE_URL = 'https://ad.360yield-basic.com';
const PB_ENDPOINT = 'pb';
const EXTEND_URL = 'https://pbs.360yield.com/openrtb2/auction';
const IFRAME_SYNC_URL = 'https://hb.360yield.com/prebid-universal-creative/load-cookie.html';

const VIDEO_PARAMS = {
  DEFAULT_MIMES: ['video/mp4'],
  PLACEMENT_TYPE: {
    INSTREAM: 1,
    OUTSTREAM: 3,
  }
};

export const spec = {
  code: BIDDER_CODE,
  gvlid: 253,
  aliases: ['id'],
  supportedMediaTypes: [BANNER, NATIVE, VIDEO],
  syncStore: { extendMode: false, placementId: null },

  /**
   * Determines whether or not the given bid request is valid.
   *
   * @param {object} bid The bid to validate.
   * @return boolean True if this is a valid bid, and false otherwise.
   */
  isBidRequestValid(bid) {
    return !!(bid && bid.params && (bid.params.placementId || (bid.params.placementKey && bid.params.publisherId)));
  },

  /**
   * Make a server request from the list of BidRequests.
   *
   * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server.
   * @param bidderRequest
   * @return ServerRequest Info describing the request to the server.
   */
  buildRequests(bidRequests, bidderRequest) {
    // Save a placement id to send it to the ad server when fetching the user syncs
    this.syncStore.placementId = this.syncStore.placementId || bidRequests[0].params.placementId;
    return ID_REQUEST.buildServerRequests(bidRequests, bidderRequest);
  },

  /**
   * Unpack the response from the server into a list of bids.
   *
   * @param {*} serverResponse A successful response from the server.
   * @param bidderRequest
   * @return {Bid[]} An array of bids which were nested inside the server.
   */
  interpretResponse(serverResponse, { ortbRequest }) {
    return CONVERTER.fromORTB({request: ortbRequest, response: serverResponse.body}).bids;
  },

  /**
   * Register the user sync pixels which should be dropped after the auction.
   *
   * @param {SyncOptions} syncOptions Which user syncs are allowed?
   * @param {ServerResponse[]} serverResponses List of server's responses.
   * @return {UserSync[]} The user syncs which should be dropped.
   */
  getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
    if (config.getConfig('coppa') === true || !hasPurpose1Consent(gdprConsent)) {
      return [];
    }

    const syncs = [];
    if ((this.syncStore.extendMode || !syncOptions.pixelEnabled) && syncOptions.iframeEnabled) {
      const { gdprApplies, consentString } = gdprConsent || {};
      const bidders = new Set();
      if (this.syncStore.extendMode && serverResponses) {
        serverResponses.forEach(response => {
          if (!response?.body?.ext?.responsetimemillis) return;
          Object.keys(response.body.ext.responsetimemillis).forEach(b => bidders.add(b))
        })
      }
      syncs.push({
        type: 'iframe',
        url: IFRAME_SYNC_URL +
          `?placement_id=${this.syncStore.placementId}` +
          (this.syncStore.extendMode ? '&pbs=1' : '') +
          (typeof gdprApplies === 'boolean' ? `&gdpr=${Number(gdprApplies)}` : '') +
          (consentString ? `&gdpr_consent=${consentString}` : '') +
          (uspConsent ? `&us_privacy=${encodeURIComponent(uspConsent)}` : '') +
          (bidders.size ? `&bidders=${[...bidders].join(',')}` : '')
      });
    } else if (syncOptions.pixelEnabled) {
      serverResponses.forEach(response => {
        const syncArr = deepAccess(response, `body.ext.${BIDDER_CODE}.sync`, []);
        syncArr.forEach(url => {
          if (!syncs.some(sync => sync.url === url)) {
            syncs.push({ type: 'image', url });
          }
        });
      });
    }

    return syncs;
  }
};

registerBidder(spec);

export const CONVERTER = ortbConverter({
  context: {
    ttl: CREATIVE_TTL,
    nativeRequest: {
      eventtrackers: [
        {event: 1, methods: [1, 2]},
      ]
    }
  },
  imp(buildImp, bidRequest, context) {
    const imp = buildImp(bidRequest, context);
    imp.secure = Number(window.location.protocol === 'https:');
    if (!imp.bidfloor && bidRequest.params.bidFloor) {
      imp.bidfloor = bidRequest.params.bidFloor;
      imp.bidfloorcur = getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || 'USD'
    }
    const bidderParamsPath = context.extendMode ? 'ext.prebid.bidder.improvedigital' : 'ext.bidder';
    const placementId = bidRequest.params.placementId;
    if (placementId) {
      deepSetValue(imp, `${bidderParamsPath}.placementId`, placementId);
      if (context.extendMode) {
        deepSetValue(imp, 'ext.prebid.storedrequest.id', '' + placementId);
      }
    } else {
      deepSetValue(imp, `${bidderParamsPath}.publisherId`, getBidIdParameter('publisherId', bidRequest.params));
      deepSetValue(imp, `${bidderParamsPath}.placementKey`, getBidIdParameter('placementKey', bidRequest.params));
    }
    deepSetValue(imp, `${bidderParamsPath}.keyValues`, getBidIdParameter('keyValues', bidRequest.params) || undefined);

    return imp;
  },
  request(buildRequest, imps, bidderRequest, context) {
    const request = buildRequest(imps, bidderRequest, context);
    mergeDeep(request, {
      id: getUniqueIdentifierStr(),
      source: {
        // TODO: once https://github.com/prebid/Prebid.js/issues/8573 is resolved, this should be handled by the base ortbConverter logic
        tid: context.bidRequests[0].transactionId,
      },
      ext: {
        improvedigital: {
          sdk: {
            name: 'pbjs',
            version: '$prebid.version$',
          }
        }
      },
    });
    return request;
  },
  bidResponse(buildBidResponse, bid, context) {
    if (!bid.adm || !bid.price || bid.hasOwnProperty('errorCode')) {
      return;
    }
    const {bidRequest} = context;
    context.mediaType = (() => {
      const requestMediaTypes = Object.keys(bidRequest.mediaTypes);
      if (requestMediaTypes.length === 1) return requestMediaTypes[0];
      // Detect media type for multi-format response
      if (bid.adm.search(/^(<\?xml|<vast)/i) !== -1) {
        return VIDEO;
      } else if (bid.adm[0] === '{') {
        return NATIVE;
      } else {
        return BANNER;
      }
    })();
    const bidResponse = buildBidResponse(bid, context);
    const idExt = deepAccess(bid, `ext.${BIDDER_CODE}`, {});
    Object.assign(bidResponse, {
      dealId: (typeof idExt.buying_type === 'string' && idExt.buying_type !== 'rtb') ? idExt.line_item_id : undefined,
      netRevenue: idExt.is_net || false,
    })
    if (bidResponse.mediaType === VIDEO && ID_REQUEST.isOutstreamVideo(bidRequest)) {
      Object.assign(bidResponse, {
        adResponse: { content: bidResponse.vastXml },
        renderer: ID_OUTSTREAM.createRenderer(bidRequest)
      })
    }
    ID_RAZR.forwardBid({bidRequest, bid: bidResponse});
    return bidResponse;
  },
  overrides: {
    imp: {
      banner(fillImpBanner, imp, bidRequest, context) {
        // override to disregard banner.sizes if usePrebidSizes is not set
        if (!bidRequest.mediaTypes[BANNER]) return;
        if (config.getConfig('improvedigital.usePrebidSizes') !== true) {
          const banner = Object.assign({}, bidRequest.mediaTypes[BANNER], {sizes: null});
          bidRequest = {...bidRequest, mediaTypes: {[BANNER]: banner}}
        }
        fillImpBanner(imp, bidRequest, context);
      },
      video(fillImpVideo, imp, bidRequest, context) {
        // override to use video params from both mediaTypes.video and bidRequest.params.video
        if (!bidRequest.mediaTypes[VIDEO]) return;
        const video = Object.assign(
          {mimes: VIDEO_PARAMS.DEFAULT_MIMES},
          bidRequest.mediaTypes[VIDEO],
          bidRequest.params?.video
        )
        fillImpVideo(
          imp,
          {...bidRequest, mediaTypes: {[VIDEO]: video}},
          context
        );
        deepSetValue(imp, 'ext.is_rewarded_inventory', (video.rewarded === 1 || deepAccess(video, 'ext.rewarded') === 1) || undefined);
        if (!imp.video.placement && ID_REQUEST.isOutstreamVideo(bidRequest)) {
          // fillImpVideo will have already set placement = 1 for instream
          imp.video.placement = VIDEO_PARAMS.PLACEMENT_TYPE.OUTSTREAM;
        }
      }
    },
    request: {
      gdprAddtlConsent(setAddtlConsent, ortbRequest, bidderRequest) {
        const additionalConsent = bidderRequest?.gdprConsent?.addtlConsent;
        if (!additionalConsent) {
          return;
        }
        if (spec.syncStore.extendMode) {
          setAddtlConsent(ortbRequest, bidderRequest);
          return;
        }
        if (additionalConsent && additionalConsent.indexOf('~') !== -1) {
          // Google Ad Tech Provider IDs
          const atpIds = additionalConsent.substring(additionalConsent.indexOf('~') + 1);
          if (atpIds) {
            deepSetValue(
              ortbRequest,
              'user.ext.consented_providers_settings.consented_providers',
              atpIds.split('.').map(id => parseInt(id, 10))
            );
          }
        }
      }
    }
  }
})

const ID_REQUEST = {
  buildServerRequests(bidRequests, bidderRequest) {
    const globalExtendMode = config.getConfig('improvedigital.extend') === true;
    const requests = [];
    const singleRequestMode = config.getConfig('improvedigital.singleRequest') === true;

    const extendBids = [];
    const adServerBids = [];

    function adServerUrl(extendMode, publisherId) {
      if (extendMode) {
        return EXTEND_URL;
      }
      const urlSegments = [];
      urlSegments.push(hasPurpose1Consent(bidderRequest?.gdprConsent) ? AD_SERVER_BASE_URL : BASIC_ADS_BASE_URL)
      if (publisherId) {
        urlSegments.push(publisherId)
      }
      urlSegments.push(PB_ENDPOINT)
      return urlSegments.join('/');
    }

    function formatRequest(bidRequests, publisherId, extendMode) {
      const ortbRequest = CONVERTER.toORTB({bidRequests, bidderRequest, context: {extendMode}});
      return {
        method: 'POST',
        url: adServerUrl(extendMode, publisherId),
        data: JSON.stringify(ortbRequest),
        ortbRequest,
        bidderRequest
      }
    }

    let publisherId = null;
    bidRequests.map((bidRequest) => {
      const bidParamsPublisherId = bidRequest.params.publisherId;
      const extendModeEnabled = this.isExtendModeEnabled(globalExtendMode, bidRequest.params);
      if (singleRequestMode) {
        if (!publisherId) {
          publisherId = bidParamsPublisherId;
        } else if (bidParamsPublisherId && publisherId !== bidParamsPublisherId) {
          throw new Error(`All Improve Digital placements in a single call must have the same publisherId. Please check your 'params.publisherId' or turn off the single request mode.`);
        }
        extendModeEnabled ? extendBids.push(bidRequest) : adServerBids.push(bidRequest);
      } else {
        requests.push(formatRequest([bidRequest], bidParamsPublisherId, extendModeEnabled));
      }
    });

    if (!singleRequestMode) {
      return requests;
    }
    // In the single request mode, split imps between those going to the ad server and those going to extend server
    if (extendBids.length) {
      requests.push(formatRequest(extendBids, publisherId, true));
    }
    if (adServerBids.length) {
      requests.push(formatRequest(adServerBids, publisherId, false));
    }

    return requests;
  },

  isExtendModeEnabled(globalExtendMode, bidParams) {
    const extendMode = typeof bidParams.extend === 'boolean' ? bidParams.extend : globalExtendMode;
    if (extendMode && !spec.syncStore.extendMode) {
      spec.syncStore.extendMode = true;
    }
    return extendMode;
  },

  isOutstreamVideo(bidRequest) {
    return deepAccess(bidRequest, 'mediaTypes.video.context') === 'outstream';
  },

};

const ID_OUTSTREAM = {
  RENDERER_URL: 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js',
  createRenderer(bidRequest) {
    const renderer = Renderer.install({
      id: bidRequest.adUnitCode,
      url: this.RENDERER_URL,
      config: deepAccess(bidRequest, 'renderer.options'),
      adUnitCode: bidRequest.adUnitCode
    });
    try {
      renderer.setRender(this.render);
    } catch (err) {
      logWarn('Prebid Error calling setRender on renderer', err);
    }
    return renderer;
  },

  render(bid) {
    bid.renderer.push(() => {
      window.ANOutstreamVideo.renderAd({
        sizes: [bid.width, bid.height],
        targetId: bid.adUnitCode,
        adResponse: bid.adResponse,
        rendererOptions: bid.renderer.getConfig()
      }, ID_OUTSTREAM.handleRendererEvents.bind(null, bid));
    });
  },

  handleRendererEvents(bid, id, eventName) {
    bid.renderer.handleVideoEvent({ id, eventName });
  },
};

const ID_RAZR = {
  RENDERER_URL: 'https://cdn.360yield.com/razr/tag.js',

  forwardBid({bidRequest, bid}) {
    if (bid.mediaType !== BANNER) {
      return;
    }

    const cfg = {
      prebid: {
        bidRequest,
        bid
      }
    };

    const cfgStr = JSON.stringify(cfg).replace(/<\/script>/g, '\\x3C/script>');
    const s = `<script>window.__razr_config = ${cfgStr};</script>`;
    bid.ad = bid.ad.replace(/<body[^>]*>/, match => match + s);

    this.installListener();
  },

  installListener() {
    if (this._listenerInstalled) {
      return;
    }

    window.addEventListener('message', function(e) {
      const data = e.data?.razr?.load;
      if (!data) {
        return;
      }

      if (e.source) {
        data.source = e.source;
        if (data.id) {
          e.source.postMessage({
            razr: {
              id: data.id
            }
          }, '*');
        }
      }

      const ns = window.razr = window.razr || {};
      ns.q = ns.q || [];
      ns.q.push(data);

      if (!ns.loaded) {
        loadExternalScript(ID_RAZR.RENDERER_URL, BIDDER_CODE);
      }
    });

    this._listenerInstalled = true;
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';

const getLabel = (keyword) => {
	let label = keyword.title || keyword.wordpressId;
	if (keyword.isMentionedInLemma) label = `[ ${label} ]`;
	return label;
};

const CommentKeywordsContainer = props => (

		{props.keywords.map(keyword => (
			<RaisedButton
				key={keyword._id}
				className="comment-keyword paper-shadow"
				onClick={props.keywordOnClick.bind(null, keyword)}
				data-id={keyword._id}
				label={getLabel(keyword)}
			/>
		))}

);
CommentKeywordsContainer.propTypes = {
	keywords: React.PropTypes.arrayOf(React.PropTypes.shape({
		_id: React.PropTypes.string.isRequired,
		title: React.PropTypes.string,
		wordpressId: React.PropTypes.number,
	})).isRequired,
	keywordOnClick: React.PropTypes.func.isRequired,
};

export default CommentKeywordsContainer;
<commit_msg>if a keyword isnt mentioned in lemma use brackets<commit_after>import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';

const getLabel = (keyword) => {
	let label = keyword.title || keyword.wordpressId;
	if (!keyword.isMentionedInLemma) label = `[ ${label} ]`;
	return label;
};

const CommentKeywordsContainer = props => (

		{props.keywords.map(keyword => (
			<RaisedButton
				key={keyword._id}
				className="comment-keyword paper-shadow"
				onClick={props.keywordOnClick.bind(null, keyword)}
				data-id={keyword._id}
				label={getLabel(keyword)}
			/>
		))}

);
CommentKeywordsContainer.propTypes = {
	keywords: React.PropTypes.arrayOf(React.PropTypes.shape({
		_id: React.PropTypes.string.isRequired,
		title: React.PropTypes.string,
		wordpressId: React.PropTypes.number,
	})).isRequired,
	keywordOnClick: React.PropTypes.func.isRequired,
};

export default CommentKeywordsContainer;
<|endoftext|>


<commit_before>var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var videoCommon = require("./videoplayer-common");
var utils = require("utils/utils");
global.moduleMerge(videoCommon, exports);
function onVideoSourcePropertyChanged(data) {
    var video = data.object;
    if (!video.android) {
        return;
    }
    video._setNativeVideo(data.newValue ? data.newValue.android : null);
}
// register the setNativeValue callback
videoCommon.Video.videoSourceProperty.metadata.onSetNativeValue = onVideoSourcePropertyChanged;
var Video = (function (_super) {
    __extends(Video, _super);
    function Video() {
        _super.apply(this, arguments);
    }
    Object.defineProperty(Video.prototype, "android", {
        get: function () {
            return this._android;
        },
        enumerable: true,
        configurable: true
    });
    Video.prototype._createUI = function () {
        var that = new WeakRef(this);
        this._android = new android.widget.VideoView(this._context);
        var _mMediaController = new android.widget.MediaController(this._context);
        this._android.setMediaController(_mMediaController);
        _mMediaController.setAnchorView(this._android);
        if (this.src) {
            if (utils.isFileOrResourcePath(this.src) === true) {
                console.log('src isFileOrResourcePath = TRUE');
                console.log('fileOrResource src: ' + this.src);
                var url = android.net.Uri.parse(this.src);
                this._android.setVideoURI(url);
            }
            else {
                console.log('src isFileOrResourcePath = FALSE');
                // var url: string = android.net.Uri.parse(this.src);
                this._android.setVideoPath(this.src);
            }
        }
        if (this.autoplay === true) {
            this._android.requestFocus();
            this._android.start();
        }
        if (this.finishedCallback) {
            // Create the Complete Listener - this is triggered once a video reaches the end
            this._android.setOnCompletionListener(new android.media.MediaPlayer.OnCompletionListener({
                get owner() {
                    return that.get();
                },
                onCompletion: function (v) {
                    if (this.owner) {
                        this.owner._emit(videoCommon.Video.finishedEvent);
                    }
                }
            }));
        }
    };
    Video.prototype._setNativeVideo = function (nativeVideo) {
        console.log('_setNativeVideo(): ' + nativeVideo);
        this.android.video = nativeVideo;
    };
    Video.prototype.setNativeSource = function (nativePlayerSrc) {
        this.src = nativePlayerSrc;
    };
    return Video;
})(videoCommon.Video);
exports.Video = Video;
<commit_msg>Fix so that Android can load local files.<commit_after>var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var fs = require('file-system');

var videoCommon = require("./videoplayer-common");
var utils = require("utils/utils");
global.moduleMerge(videoCommon, exports);
function onVideoSourcePropertyChanged(data) {
    var video = data.object;
    if (!video.android) {
        return;
    }
    video._setNativeVideo(data.newValue ? data.newValue.android : null);
}
// register the setNativeValue callback
videoCommon.Video.videoSourceProperty.metadata.onSetNativeValue = onVideoSourcePropertyChanged;
var Video = (function (_super) {
    __extends(Video, _super);
    function Video() {
        _super.apply(this, arguments);
    }
    Object.defineProperty(Video.prototype, "android", {
        get: function () {
            return this._android;
        },
        enumerable: true,
        configurable: true
    });
    Video.prototype._createUI = function () {
        var that = new WeakRef(this);
        this._android = new android.widget.VideoView(this._context);
        var _mMediaController = new android.widget.MediaController(this._context);
        this._android.setMediaController(_mMediaController);
        _mMediaController.setAnchorView(this._android);
        if (this.src) {
            var isUrl = false;
            if (this.src.indexOf("://") !== -1) {
               if (this.src.indexOf('res://') === -1) {
                    isUrl = true;
               }
            }

            if (!isUrl) {
                var currentPath = fs.knownFolders.currentApp().path;
                if (this.src[1] === '/' && (this.src[0] === '.' || this.src[0] === '~')) {
                    this.src = this.src.substr(2);
                }
                this.src = currentPath + '/' + this.src;
                console.log('src isFileOrResourcePath = TRUE', this.src);
                console.log('fileOrResource src: ' + this.src);
                var url = android.net.Uri.parse(this.src);
                this._android.setVideoURI(url);
            }
            else {
                console.log('src isFileOrResourcePath = FALSE');
                // var url: string = android.net.Uri.parse(this.src);
                this._android.setVideoPath(this.src);
            }
        }
        if (this.autoplay === true) {
            this._android.requestFocus();
            this._android.start();
        }
        if (this.finishedCallback) {
            // Create the Complete Listener - this is triggered once a video reaches the end
            this._android.setOnCompletionListener(new android.media.MediaPlayer.OnCompletionListener({
                get owner() {
                    return that.get();
                },
                onCompletion: function (v) {
                    if (this.owner) {
                        this.owner._emit(videoCommon.Video.finishedEvent);
                    }
                }
            }));
        }
    };
    Video.prototype._setNativeVideo = function (nativeVideo) {
        console.log('_setNativeVideo(): ' + nativeVideo);
        this.android.video = nativeVideo;
    };
    Video.prototype.setNativeSource = function (nativePlayerSrc) {
        this.src = nativePlayerSrc;
    };
    return Video;
})(videoCommon.Video);
exports.Video = Video;
<|endoftext|>


<commit_before>import React from 'react'
import NBA from 'nba'

import Player from './Player'
import Players from './Players'
import getPlayer from '../api/getPlayer'

import MDSpinner from "react-md-spinner"
import Autosuggest from 'react-autosuggest'

module.exports = ({state, dispatch}) => {
  function handleNameChange (e) {
    e.preventDefault()
    dispatch({type: 'HANDLE_FORM_NAME_CHANGE', payload: e.target.value})
  }
  function addPlayer (e) {
    e.preventDefault()
    getPlayer(state, dispatch)
    dispatch({type: 'HANDLE_FORM_NAME_CHANGE', payload: ""})
  }
  function getSuggestions (value) {
    if (value) {
      return NBA.searchPlayers(value)
    }
    return null
  }
  function getSuggestionValue (player) {
    return player.fullName
  }
  function renderSuggestion (player) {
    return(

        player.fullName

    )
  }
  const onSuggestionsFetchRequested = () => {
    dispatch({type: 'ADD_SUGGESTIONS', payload: getSuggestions(state.form.name)})
  }

  // Autosuggest will call this function every time you need to clear suggestions.
  const onSuggestionsClearRequested = () => {
    dispatch({type: 'ADD_SUGGESTIONS', payload: []})
  }
  const inputProps = {
    placeholder: "Type A Player's Name",
    value: null,
    onChange: handleNameChange
  }
  return (

Compare Players

        <form>
          Player Name:
          <Autosuggest
            suggestions={state.form.suggestions}
            getSuggestionValue={getSuggestionValue}
            renderSuggestion={renderSuggestion}
            onSuggestionsFetchRequested={onSuggestionsFetchRequested}
            onSuggestionsClearRequested={onSuggestionsClearRequested}
            inputProps={inputProps}
          />
          <input type="text" name="playerName" placeholder="name" value={ state.form.name ? state.form.name : ""} onChange={handleNameChange}></input>
          <input className="submit" type="submit" value="ADD PLAYER" onClick={addPlayer} ></input>
        </form>

        {state.isLoading ? <MDSpinner size={80} className="spinner" /> : <Players state={state} dispatch={dispatch}/>}

  )
}

const suggestedPlayers = [
  {name: "Stephen Curry"},
  {name: "Kyrie Irving"}
]
<commit_msg>Remove autofill component for now<commit_after>import React from 'react'
import NBA from 'nba'

import Player from './Player'
import Players from './Players'
import getPlayer from '../api/getPlayer'

import MDSpinner from "react-md-spinner"
import Autosuggest from 'react-autosuggest'

module.exports = ({state, dispatch}) => {
  function handleNameChange (e) {
    e.preventDefault()
    dispatch({type: 'HANDLE_FORM_NAME_CHANGE', payload: e.target.value})
  }
  function addPlayer (e) {
    e.preventDefault()
    getPlayer(state, dispatch)
    dispatch({type: 'HANDLE_FORM_NAME_CHANGE', payload: ""})
  }
  function getSuggestions (value) {
    if (value) {
      return NBA.searchPlayers(value)
    }
    return null
  }
  function getSuggestionValue (player) {
    return player.fullName
  }
  function renderSuggestion (player) {
    return(

        player.fullName

    )
  }
  const onSuggestionsFetchRequested = () => {
    dispatch({type: 'ADD_SUGGESTIONS', payload: getSuggestions(state.form.name)})
  }

  // Autosuggest will call this function every time you need to clear suggestions.
  const onSuggestionsClearRequested = () => {
    dispatch({type: 'ADD_SUGGESTIONS', payload: []})
  }
  const inputProps = {
    placeholder: "Type A Player's Name",
    value: null,
    onChange: handleNameChange
  }
  return (

Compare Players

        <form>
          Player Name:
          <input type="text" name="playerName" placeholder="name" autoComplete="off" value={ state.form.name ? state.form.name : ""} onChange={handleNameChange}></input>
          <input className="submit" type="submit" value="ADD PLAYER" onClick={addPlayer} ></input>
        </form>

        {state.isLoading ? <MDSpinner size={80} className="spinner" /> : <Players state={state} dispatch={dispatch}/>}

  )
}

const suggestedPlayers = [
  {name: "Stephen Curry"},
  {name: "Kyrie Irving"}
]

// <Autosuggest
//   suggestions={state.form.suggestions}
//   getSuggestionValue={getSuggestionValue}
//   renderSuggestion={renderSuggestion}
//   onSuggestionsFetchRequested={onSuggestionsFetchRequested}
//   onSuggestionsClearRequested={onSuggestionsClearRequested}
//   inputProps={inputProps}
// />
<|endoftext|>


<commit_before>"use strict";

var eon = eon || {};
eon.c = {
  observers: {},
  message: function(message, env, channel) {

    var i = 0;
    while(i < eon.c.observers[channel].length) {
      eon.c.observers[channel][i](message, env, channel);
      i++;
    }

  },
  subscribe: function(pubnub, channel, connect, callback) {

    if(typeof(eon.c.observers[channel]) == "undefined") {

      eon.c.observers[channel] = [callback];

      pubnub.subscribe({
        channel: channel,
        connect: connect,
        message: function(message, env, channel) {

          eon.c.message(message, env, channel);

        }
      });

    } else {
      eon.c.observers[channel].push(callback);
    }

  },
  create: function(options) {

    var self = this;
    var error = false;

    self.chart = false;

    self.pubnub = options.pubnub || PUBNUB || false;

    if(!self.pubnub) {
      error = "PubNub not found. See http://www.pubnub.com/docs/javascript/javascript-sdk.html#_where_do_i_get_the_code";
    }

    options.channel = options.channel || false;
    options.generate = options.generate || {};
    options.flow = options.flow || false;
    options.flow.length = options.flow.length || 0;
    options.limit = options.limit || 10;
    options.history = options.history || false;

    options.rate = options.rate || 1000;

    options.message = options.message || function(){};
    options.connect = options.connect || function(){};

    if(options.limit > 100) {
      options.limit = 100;
    }

    if(!options.channel) {
      error = "No channel supplied.";
    }

    var all_messages = [];
    var page = function() {

      all_messages = [];
      var i = 0;

      var getAllMessages = function(timetoken) {
         self.pubnub.history({
          count: options.limit,
          channel: options.channel,
          start: timetoken,
           callback: function(payload) {

             var msgs = payload[0];
             var start = payload[1];
             var end = payload[2];

             if (msgs !== undefined && msgs.length) {

               msgs.reverse();

              i = 0;
               while(i < msgs.length) {
                 all_messages.push(msgs[[i]]);
                 i++;
               }

             }

             if (msgs.length && all_messages.length < options.limit) {
               getAllMessages(start);
             } else {

              var data = [];

               i = 0;
               while(i < all_messages.length) {

                var columns = all_messages[i].columns;

                 for(var j in columns) {

                    if(i === 0) {
                      data[j] = [];
                      data[j].push(columns[j][0]);
                    }

                    data[j].push(columns[j][1]);

                 }

                 i++;

               }

               // ready to go
               data.reverse();
               self.chart.load({columns: data});

             }

           }
         });
       };

       getAllMessages();

    };

    var buffer = [];
    var needsTrim = function() {

      buffer = self.chart.data();

      var i = 0;

      while(i < buffer.length) {
        if(buffer[i].values.length > options.limit) {
          return buffer[i].values.length - options.limit;
        }
        i++;
      }

      return false;

    };

    var lastData = [];
    var mapMessage = function(message) {

      var i = 0;

      // if we have data already
      if(lastData.length) {

        // loop through the new message
        while(i < message.columns.length) {

          var j = 0;
          var found = false;

          // and compare it against the old message
          while(j < lastData.length) {

            // if it's x, then see if the new one is larger
            if(
              message.columns[i][0] == 'x' &&
              lastData[j][0] == 'x'
            ) {

              if(message.columns[i][1] > lastData[j][1]) {
                lastData[j][1] = message.columns[i][1];
              }

            // if they have the same key, overwrite the buffer              }
            }

            if(lastData[j][0] == message.columns[i][0]) {
              lastData[j][1] = message.columns[i][1];
              found = true;
            }

            j++;

          }

          if(!found) {
            lastData[j] = message.columns[i];
          }

          i++;

        }

      } else {
        lastData = message.columns;
      }

    };

    var boot = function() {

      options.generate.data.columns = [];
      self.chart = c3.generate(options.generate);

      if(options.history) {
        page();
      }

      eon.c.subscribe(self.pubnub, options.channel, options.connect, function(message, env, channel) {

        options.message(message, env, channel);

        mapMessage(message);

      });

      setInterval(function() {

        if(lastData.length) {

          if(options.flow) {

            if(options.flow === true) {
              options.flow = {};
            }

            var trimLength = needsTrim();

            if(trimLength)  {
              options.flow.length = trimLength;
            }

            options.flow.columns = lastData;

            self.chart.flow(options.flow);

          } else {
            self.chart.load(lastData);
          }

        }

      }, options.rate);

      return self;

    };

    if(error) {
      console.error("EON: " + error);
    } else {
      boot();
    }

    return self.chart;

  }
};
eon.chart = function(o) {
  return new eon.c.create(o);
};<commit_msg>load data fix<commit_after>"use strict";

var eon = eon || {};
eon.c = {
  observers: {},
  message: function(message, env, channel) {

    var i = 0;
    while(i < eon.c.observers[channel].length) {
      eon.c.observers[channel][i](message, env, channel);
      i++;
    }

  },
  subscribe: function(pubnub, channel, connect, callback) {

    if(typeof(eon.c.observers[channel]) == "undefined") {

      eon.c.observers[channel] = [callback];

      pubnub.subscribe({
        channel: channel,
        connect: connect,
        message: function(message, env, channel) {

          eon.c.message(message, env, channel);

        }
      });

    } else {
      eon.c.observers[channel].push(callback);
    }

  },
  create: function(options) {

    var self = this;
    var error = false;

    self.chart = false;

    self.pubnub = options.pubnub || PUBNUB || false;

    if(!self.pubnub) {
      error = "PubNub not found. See http://www.pubnub.com/docs/javascript/javascript-sdk.html#_where_do_i_get_the_code";
    }

    options.channel = options.channel || false;
    options.generate = options.generate || {};
    options.flow = options.flow || false;
    if(options.flow) {
      options.flow.length = options.flow.length || 0;
    }
    options.limit = options.limit || 10;
    options.history = options.history || false;

    options.rate = options.rate || 1000;

    options.message = options.message || function(){};
    options.connect = options.connect || function(){};

    if(options.limit > 100) {
      options.limit = 100;
    }

    if(!options.channel) {
      error = "No channel supplied.";
    }

    var all_messages = [];
    var page = function() {

      all_messages = [];
      var i = 0;

      var getAllMessages = function(timetoken) {
         self.pubnub.history({
          count: options.limit,
          channel: options.channel,
          start: timetoken,
           callback: function(payload) {

             var msgs = payload[0];
             var start = payload[1];
             var end = payload[2];

             if (msgs !== undefined && msgs.length) {

               msgs.reverse();

              i = 0;
               while(i < msgs.length) {
                 all_messages.push(msgs[[i]]);
                 i++;
               }

             }

             if (msgs.length && all_messages.length < options.limit) {
               getAllMessages(start);
             } else {

              var data = [];

               i = 0;
               while(i < all_messages.length) {

                var columns = all_messages[i].columns;

                 for(var j in columns) {

                    if(i === 0) {
                      data[j] = [];
                      data[j].push(columns[j][0]);
                    }

                    data[j].push(columns[j][1]);

                 }

                 i++;

               }

               // ready to go
               data.reverse();
               self.chart.load({columns: data});

             }

           }
         });
       };

       getAllMessages();

    };

    var buffer = [];
    var needsTrim = function() {

      buffer = self.chart.data();

      var i = 0;

      while(i < buffer.length) {
        if(buffer[i].values.length > options.limit) {
          return buffer[i].values.length - options.limit;
        }
        i++;
      }

      return false;

    };

    var lastData = [];
    var mapMessage = function(message) {

      var i = 0;

      // if we have data already
      if(lastData.length) {

        // loop through the new message
        while(i < message.columns.length) {

          var j = 0;
          var found = false;

          // and compare it against the old message
          while(j < lastData.length) {

            // if it's x, then see if the new one is larger
            if(
              message.columns[i][0] == 'x' &&
              lastData[j][0] == 'x'
            ) {

              if(message.columns[i][1] > lastData[j][1]) {
                lastData[j][1] = message.columns[i][1];
              }

            // if they have the same key, overwrite the buffer              }
            }

            if(lastData[j][0] == message.columns[i][0]) {
              lastData[j][1] = message.columns[i][1];
              found = true;
            }

            j++;

          }

          if(!found) {
            lastData[j] = message.columns[i];
          }

          i++;

        }

      } else {
        lastData = message.columns;
      }

    };

    var boot = function() {

      options.generate.data.columns = [];
      self.chart = c3.generate(options.generate);

      if(options.history) {
        page();
      }

      eon.c.subscribe(self.pubnub, options.channel, options.connect, function(message, env, channel) {

        options.message(message, env, channel);

        mapMessage(message);

      });

      setInterval(function() {

        if(lastData.length) {

          if(options.flow) {

            if(options.flow === true) {
              options.flow = {};
            }

            var trimLength = needsTrim();

            if(trimLength)  {
              options.flow.length = trimLength;
            }

            options.flow.columns = lastData;

            self.chart.flow(options.flow);

          } else {
            self.chart.load({
              columns: lastData
            });
          }

        }

      }, options.rate);

      return self;

    };

    if(error) {
      console.error("EON: " + error);
    } else {
      boot();
    }

    return self.chart;

  }
};
eon.chart = function(o) {
  return new eon.c.create(o);
};<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';

function Home() {
  const repoReadmeLink = 'https://github.com/rafrex/spa-github-pages#readme';
  return (

        Сайтта курулуш иштери жүргүзүлүүдө.

        Бул долбоор GitHub Pages'те орнотулган жана бул
        калыптын негизинде кураштырылган.

Төмөнкүлөр бул жерде жөн эле турат :)

<Link to="/posts/zhalpy/test">Sample post</Link>

<Link to="/categories/kategoriyasyz">Sample category</Link>

<Link to="/example">Example page</Link>

<Link to="/example/two-deep?field1=foo&field2=bar#boom!">
        Example two deep with query and hash
      </Link>

  );
}

export default Home;
<commit_msg>Render all posts in Home component<commit_after>import React from 'react'
import Posts from './Posts'

function Home() {
  const repoReadmeLink = 'https://github.com/rafrex/spa-github-pages#readme';
  return (

      <Posts />

        Бул долбоор GitHub Pages'те орнотулган жана бул
        калыптын негизинде кураштырылган.

  );
}

export default Home;
<|endoftext|>


<commit_before>var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.addEventListener("offline", checkConnection, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
        screen.lockOrientation('portrait');
        localStorage.setItem("saldo_actual",0);
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        getDeviceProperty();
        detectGEO();
    }
};

function detectGEO(){
  var options = {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 75000
  };
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
  } else {
      console.log('Geolocalización no soportada');
  }
}

// onSuccess Geolocation    //
function onSuccess(position) {
  localStorage.removeItem("position");
  lat1= position.coords.latitude;
  lng1= position.coords.longitude;
  var pos= {lat:lat1,lng:lng1};
  localStorage.setItem("position",JSON.stringify(pos));
  console.log('Coordenadas detectadas');
}
function onError(error) {
  console.log('Error detectando coordenadas');
}

function getDeviceProperty()
{
     var deviceOS  = device.platform  ;  //fetch the device operating system
     var deviceOSVersion = device.version ;  //fetch the device OS version
     localStorage.setItem("OS",deviceOS);
}

function checkConnection() {
    alert("Conexion");
    var state=true;
    var networkState = navigator.connection.type;
    var states = {};
    states[Connection.UNKNOWN]  = 'Unknown connection';
    states[Connection.ETHERNET] = 'Ethernet connection';
    states[Connection.WIFI]     = 'WiFi connection';
    states[Connection.CELL_2G]  = 'Cell 2G connection';
    states[Connection.CELL_3G]  = 'Cell 3G connection';
    states[Connection.CELL_4G]  = 'Cell 4G connection';
    states[Connection.CELL]     = 'Cell generic connection';
    states[Connection.NONE]     = 'No network connection';

    if(states[networkState]=='No network connection'){
        navigator.notification.beep(1);
        alert('Internet es requerido!');
        state=false;
    }else{
        alert('WIFI disponible!');
    }
    return state;
}<commit_msg>conex<commit_after>var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.addEventListener("offline", checkConnection, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
        screen.lockOrientation('portrait');
        localStorage.setItem("saldo_actual",0);
    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        getDeviceProperty();
        detectGEO();
    }
};

function detectGEO(){
  var options = {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 75000
  };
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
  } else {
      console.log('Geolocalización no soportada');
  }
}

// onSuccess Geolocation    //
function onSuccess(position) {
  localStorage.removeItem("position");
  lat1= position.coords.latitude;
  lng1= position.coords.longitude;
  var pos= {lat:lat1,lng:lng1};
  localStorage.setItem("position",JSON.stringify(pos));
  console.log('Coordenadas detectadas');
}
function onError(error) {
  console.log('Error detectando coordenadas');
}

function getDeviceProperty()
{
     var deviceOS  = device.platform  ;  //fetch the device operating system
     var deviceOSVersion = device.version ;  //fetch the device OS version
     localStorage.setItem("OS",deviceOS);
}

function checkConnection() {
    alert("Conexion");
    var state=true;
    var networkState = navigator.connection.type;
    var states = {};
    states[Connection.UNKNOWN]  = 'Unknown connection';
    states[Connection.ETHERNET] = 'Ethernet connection';
    states[Connection.WIFI]     = 'WiFi connection';
    states[Connection.CELL_2G]  = 'Cell 2G connection';
    states[Connection.CELL_3G]  = 'Cell 3G connection';
    states[Connection.CELL_4G]  = 'Cell 4G connection';
    states[Connection.CELL]     = 'Cell generic connection';
    states[Connection.NONE]     = 'No network connection';

    alert(states[networkState]);
    if(states[networkState]=='No network connection'){
        navigator.notification.beep(1);
        alert('Internet es requerido!');
        state=false;
    }else{
        alert('WIFI disponible!');
    }
    return state;
}<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import {
  View,
  ListView,
  Text,
  TouchableOpacity,
  StyleSheet,
  Alert,
  Platform,
} from 'react-native';
import colors from '../config/colors';
import Carpooler from '../components/Carpooler';
import { connectActionSheet } from '@exponent/react-native-action-sheet';
import { withNavigation } from '@exponent/ex-navigation';
import ElevatedView from 'react-native-elevated-view';
import { maybeOpenURL } from 'react-native-app-link';
import connectDropdownAlert from '../utils/connectDropdownAlert';
import { observer } from 'mobx-react/native';
import { Notifications } from 'exponent';

@withNavigation
@connectActionSheet
@connectDropdownAlert
@observer
export default class Ride extends Component {
  static propTypes = {
    event: PropTypes.object.isRequired,
    navigator: PropTypes.object,
    showActionSheetWithOptions: PropTypes.func,
    refresh: PropTypes.func,
    refreshing: PropTypes.bool,
    alertWithType: PropTypes.func.isRequired,
  };

  state = {
    passengers: [],
    pickedUpUsers: 0,
    selfIsDriver: this.props.event.yourRide.driver ===
      global.firebaseApp.auth().currentUser.uid,
  };

  componentWillMount() {
    const passengers = [];
    let pickedUpUsers = 0;
    global.firebaseApp
      .database()
      .ref('users')
      .child(this.props.event.yourRide.driver)
      .once('value')
      .then(userSnap => {
        passengers.push({
          userUID: this.props.event.yourRide.driver,
          ...userSnap.val(),
          type: 'driver',
        });

        // now get other users and push to arr
        if (this.props.event.yourRide.passengers) {
          this.props.event.yourRide.passengers.slice().forEach(pass => {
            global.firebaseApp
              .database()
              .ref('users')
              .child(pass.userUID)
              .once('value')
              .then(passSnap => {
                passengers.push({
                  ...pass,
                  ...passSnap.val(),
                  type: 'rider',
                });
                if (pass.isPickedUp) {
                  pickedUpUsers++;
                }
                this.setState(() => {
                  return {
                    passengers,
                    pickedUpUsers,
                  };
                });
              });
          });
        }
        this.setState(() => {
          return {
            passengers,
          };
        });
      })
      .catch(err => {
        this.props.alertWithType('error', 'Error', err.toString());
      });
  }

  ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

  _onOpenActionSheet = () => {
    // Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
    const options = ['Leave Ride', 'Navigate', 'Cancel'];
    const destructiveButtonIndex = 0;
    const navigateButtonIndex = 1;
    const cancelButtonIndex = 2;
    this.props.showActionSheetWithOptions(
      {
        options,
        cancelButtonIndex,
        destructiveButtonIndex,
      },
      buttonIndex => {
        if (buttonIndex === destructiveButtonIndex) {
          if (this.state.selfIsDriver) {
            Alert.alert(
              Platform.OS === 'ios' ? 'Leave Ride' : 'Leave ride',
              'Are you sure? Leaving this ride will strand your passengers. 😢',
              [
                { text: 'Cancel', style: 'cancel' },
                {
                  text: 'OK',
                  onPress: () => {
                    global.firebaseApp
                      .database()
                      .ref('schools')
                      .child(this.props.event.schoolUID)
                      .child('events')
                      .child(this.props.event.uid)
                      .child('rides')
                      .child(this.props.event.yourRide.uid)
                      .remove()
                      .then(() => {
                        Notifications.cancelScheduledNotificationAsync(
                          this.props.event.yourRide.notiID,
                        );
                        this.props.alertWithType(
                          'error',
                          '😢',
                          `You left ${this.props.event.name}.`,
                        );
                        this.props.refresh(false);
                      })
                      .catch(err => {
                        this.props.alertWithType(
                          'error',
                          'Error',
                          err.toString(),
                        );
                      });
                  },
                },
              ],
            );
          } else {
            Alert.alert(
              Platform.OS === 'ios' ? 'Leave Ride' : 'Leave ride',
              'Are you sure? Leaving this ride so not lit.',
              [
                { text: 'Cancel', style: 'cancel' },
                {
                  text: 'OK',
                  onPress: () => {
                    const passIndex = this.props.event.yourRide.passengers
                      .slice()
                      .findIndex(
                        i =>
                          i.userUID ===
                          global.firebaseApp.auth().currentUser.uid,
                      );
                    global.firebaseApp
                      .database()
                      .ref('schools')
                      .child(this.props.event.schoolUID)
                      .child('events')
                      .child(this.props.event.uid)
                      .child('rides')
                      .child(this.props.event.yourRide.uid)
                      .child('passengers')
                      .child(
                        this.props.event.yourRide.passengers[passIndex].passUID,
                      )
                      .remove()
                      .then(() => {
                        this.props.alertWithType(
                          'error',
                          '😢',
                          `You left ${this.props.event.name}.`,
                        );
                        this.props.refresh(false);
                      })
                      .catch(err => {
                        this.props.alertWithType(
                          'error',
                          'Error',
                          err.toString(),
                        );
                      });
                  },
                },
              ],
            );
          }
        }
        if (buttonIndex === navigateButtonIndex) {
          const wazeUrl = `waze://?ll=${this.props.event.location.geometry.location.lat},` +
            `${this.props.event.location.geometry.location.lng}&z=10&navigate=yes`;
          maybeOpenURL(wazeUrl, {
            appName: 'Waze',
            appStoreId: 'id323229106',
            playStoreId: 'com.waze',
          }).catch(err => {
            this.props.alertWithType('error', 'Error', err.toString());
          });
        }
      },
    );
  };

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.headerRow}>
          <Text style={styles.label}>
            {this.props.event.name.toUpperCase()}
          </Text>
          <TouchableOpacity
            style={styles.moreContainer}
            onPress={this._onOpenActionSheet}
            // onPress open an action sheet
            hitSlop={{ top: 20, bottom: 20, left: 20, right: 20 }}>
            <View style={styles.moreItem} />
            <View style={styles.moreItem} />
            <View style={styles.moreItem} />
          </TouchableOpacity>
        </View>
        <ListView
          enableEmptySections
          dataSource={this.ds.cloneWithRows(this.state.passengers)}
          renderRow={u => (
            <Carpooler
              event={this.props.event}
              refresh={this.props.refresh}
              passengers={this.state.passengers}
              pickedUpUsers={this.state.pickedUpUsers}
              refreshing={this.props.refreshing}
              user={u}
              selfIsDriver={this.state.selfIsDriver}
            />
          )}
        />
        {/* if everyone is pickedUp render 'start driving' button */}
        <Choose>
          <When
            condition={
              this.state.selfIsDriver &&
                !this.props.event.yourRide.rideStarted &&
                this.state.passengers.length > 1 &&
                this.state.pickedUpUsers === this.state.passengers.length - 1
            }>
            <TouchableOpacity
              onPress={() => Alert.alert(
                Platform.OS === 'ios' ? 'Start Ride' : 'Start ride',
                "Are you sure? Just making sure you didn't click this by mistake.",
                [
                  { text: 'Cancel', style: 'cancel' },
                  {
                    text: 'OK',
                    onPress: () => {
                      global.firebaseApp
                        .database()
                        .ref('schools')
                        .child(this.props.event.schoolUID)
                        .child('events')
                        .child(this.props.event.uid)
                        .child('rides')
                        .child(this.props.event.yourRide.uid)
                        .update(
                          {
                            rideStarted: true,
                          },
                          () => {
                            const wazeUrl = `waze://?ll=${this.props.event.location.geometry.location.lat},` +
                              `${this.props.event.location.geometry.location.lng}&z=10&navigate=yes`;
                            maybeOpenURL(wazeUrl, {
                              appName: 'Waze',
                              appStoreId: 'id323229106',
                              playStoreId: 'com.waze',
                            }).catch(err => {
                              this.props.alertWithType(
                                'error',
                                'Error',
                                err.toString(),
                              );
                            });
                          },
                        )
                        .catch(err => {
                          this.props.alertWithType(
                            'error',
                            'Error',
                            err.toString(),
                          );
                        });
                    },
                  },
                ],
              )}>
              <ElevatedView style={styles.startDrivingButton} elevation={4}>
                <Text style={styles.buttonText}>

                  START DRIVING
                </Text>
              </ElevatedView>
            </TouchableOpacity>
          </When>
          <When
            condition={
              this.state.selfIsDriver &&
                this.props.event.yourRide.rideStarted &&
                !this.props.event.yourRide.rideCompleted
            }>
            <TouchableOpacity
              onPress={() => Alert.alert(
                Platform.OS === 'ios' ? 'End Ride' : 'End ride',
                "Are you sure? Just making sure you didn't click this by mistake.",
                [
                  { text: 'Cancel', style: 'cancel' },
                  {
                    text: 'OK',
                    onPress: () => {
                      global.firebaseApp
                        .database()
                        .ref('schools')
                        .child(this.props.event.schoolUID)
                        .child('events')
                        .child(this.props.event.uid)
                        .child('rides')
                        .child(this.props.event.yourRide.uid)
                        .update(
                          {
                            rideCompleted: true,
                          },
                          () => {
                            this.props.alertWithType(
                              'success',
                              'YEET',
                              'Aye you made it!',
                            );
                          },
                        )
                        .catch(err => {
                          this.props.alertWithType(
                            'error',
                            'Error',
                            err.toString(),
                          );
                        });
                    },
                  },
                ],
              )}>
              <ElevatedView style={styles.rideCompleteButton} elevation={4}>
                <Text style={styles.buttonText}>
                  COMPLETE RIDE
                </Text>
              </ElevatedView>
            </TouchableOpacity>
          </When>
          <When
            condition={
              this.state.selfIsDriver && this.state.passengers.length === 1
            }>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              NO PASSENGERS AVAILABLE
            </Text>
          </When>
          <When
            condition={
              this.props.event.yourRide.rideStarted &&
                !this.props.event.yourRide.rideCompleted
            }>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              RIDE IN PROGRESS
            </Text>
          </When>
          <When condition={this.props.event.yourRide.rideCompleted}>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              RIDE COMPLETED
            </Text>
          </When>
        </Choose>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    paddingVertical: 8,
  },
  label: {
    fontFamily: 'open-sans-semibold',
    fontSize: 12,
    color: 'rgba(128, 128, 128, 0.7)',
  },
  headerRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginHorizontal: 8,
    paddingBottom: 4,
  },
  moreContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    width: 24,
  },
  moreItem: {
    backgroundColor: '#546E7A',
    height: 5,
    width: 5,
    borderRadius: 5,
  },
  startDrivingButton: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    marginHorizontal: 8,
    paddingVertical: 8,
    marginTop: 8,
    backgroundColor: colors.purp,
  },
  rideCompleteButton: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    marginHorizontal: 8,
    paddingVertical: 8,
    marginTop: 8,
    backgroundColor: colors.neonGreen,
  },
  buttonText: {
    fontFamily: 'open-sans-bold',
    fontSize: 18,
    color: 'white',
  },
});
<commit_msg>bracket test<commit_after>import React, { Component, PropTypes } from 'react';
import {
  View,
  ListView,
  Text,
  TouchableOpacity,
  StyleSheet,
  Alert,
  Platform,
} from 'react-native';
import colors from '../config/colors';
import Carpooler from '../components/Carpooler';
import { connectActionSheet } from '@exponent/react-native-action-sheet';
import { withNavigation } from '@exponent/ex-navigation';
import ElevatedView from 'react-native-elevated-view';
import { maybeOpenURL } from 'react-native-app-link';
import connectDropdownAlert from '../utils/connectDropdownAlert';
import { observer } from 'mobx-react/native';
import { Notifications } from 'exponent';

@withNavigation
@connectActionSheet
@connectDropdownAlert
@observer
export default class Ride extends Component {
  static propTypes = {
    event: PropTypes.object.isRequired,
    navigator: PropTypes.object,
    showActionSheetWithOptions: PropTypes.func,
    refresh: PropTypes.func,
    refreshing: PropTypes.bool,
    alertWithType: PropTypes.func.isRequired,
  };

  state = {
    passengers: [],
    pickedUpUsers: 0,
    selfIsDriver: this.props.event.yourRide.driver ===
      global.firebaseApp.auth().currentUser.uid,
  };

  componentWillMount() {
    const passengers = [];
    let pickedUpUsers = 0;
    global.firebaseApp
      .database()
      .ref('users')
      .child(this.props.event.yourRide.driver)
      .once('value')
      .then(userSnap => {
        passengers.push({
          userUID: this.props.event.yourRide.driver,
          ...userSnap.val(),
          type: 'driver',
        });

        // now get other users and push to arr
        if (this.props.event.yourRide.passengers) {
          this.props.event.yourRide.passengers.slice().forEach(pass => {
            global.firebaseApp
              .database()
              .ref('users')
              .child(pass.userUID)
              .once('value')
              .then(passSnap => {
                passengers.push({
                  ...pass,
                  ...passSnap.val(),
                  type: 'rider',
                });
                if (pass.isPickedUp) {
                  pickedUpUsers++;
                }
                this.setState(() => {
                  return {
                    passengers,
                    pickedUpUsers,
                  };
                });
              });
          });
        }
        this.setState(() => {
          return {
            passengers,
          };
        });
      })
      .catch(err => {
        this.props.alertWithType('error', 'Error', err.toString());
      });
  }

  ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

  _onOpenActionSheet = () => {
    // Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
    const options = ['Leave Ride', 'Navigate', 'Cancel'];
    const destructiveButtonIndex = 0;
    const navigateButtonIndex = 1;
    const cancelButtonIndex = 2;
    this.props.showActionSheetWithOptions(
      {
        options,
        cancelButtonIndex,
        destructiveButtonIndex,
      },
      buttonIndex => {
        if (buttonIndex === destructiveButtonIndex) {
          if (this.state.selfIsDriver) {
            Alert.alert(
              Platform.OS === 'ios' ? 'Leave Ride' : 'Leave ride',
              'Are you sure? Leaving this ride will strand your passengers. 😢',
              [
                { text: 'Cancel', style: 'cancel' },
                {
                  text: 'OK',
                  onPress: () => {
                    global.firebaseApp
                      .database()
                      .ref('schools')
                      .child(this.props.event.schoolUID)
                      .child('events')
                      .child(this.props.event.uid)
                      .child('rides')
                      .child(this.props.event.yourRide.uid)
                      .remove()
                      .then(() => {
                        Notifications.cancelScheduledNotificationAsync(
                          this.props.event.yourRide.notiID,
                        );
                        this.props.alertWithType(
                          'error',
                          '😢',
                          `You left ${this.props.event.name}.`,
                        );
                        this.props.refresh(false);
                      })
                      .catch(err => {
                        this.props.alertWithType(
                          'error',
                          'Error',
                          err.toString(),
                        );
                      });
                  },
                },
              ],
            );
          } else {
            Alert.alert(
              Platform.OS === 'ios' ? 'Leave Ride' : 'Leave ride',
              'Are you sure? Leaving this ride so not lit.',
              [
                { text: 'Cancel', style: 'cancel' },
                {
                  text: 'OK',
                  onPress: () => {
                    const passIndex = this.props.event.yourRide.passengers
                      .slice()
                      .findIndex(
                        i =>
                          i.userUID ===
                          global.firebaseApp.auth().currentUser.uid,
                      );
                    global.firebaseApp
                      .database()
                      .ref('schools')
                      .child(this.props.event.schoolUID)
                      .child('events')
                      .child(this.props.event.uid)
                      .child('rides')
                      .child(this.props.event.yourRide.uid)
                      .child('passengers')
                      .child(
                        this.props.event.yourRide.passengers[passIndex].passUID,
                      )
                      .remove()
                      .then(() => {
                        this.props.alertWithType(
                          'error',
                          '😢',
                          `You left ${this.props.event.name}.`,
                        );
                        this.props.refresh(false);
                      })
                      .catch(err => {
                        this.props.alertWithType(
                          'error',
                          'Error',
                          err.toString(),
                        );
                      });
                  },
                },
              ],
            );
          }
        }
        if (buttonIndex === navigateButtonIndex) {
          const wazeUrl = `waze://?ll=${this.props.event.location.geometry.location.lat},` +
            `${this.props.event.location.geometry.location.lng}&z=10&navigate=yes`;
          maybeOpenURL(wazeUrl, {
            appName: 'Waze',
            appStoreId: 'id323229106',
            playStoreId: 'com.waze',
          }).catch(err => {
            this.props.alertWithType('error', 'Error', err.toString());
          });
        }
      },
    );
  };

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.headerRow}>
          <Text style={styles.label}>
            {this.props.event.name.toUpperCase()}
          </Text>
          <TouchableOpacity
            style={styles.moreContainer}
            onPress={this._onOpenActionSheet}
            // onPress open an action sheet
            hitSlop={{ top: 20, bottom: 20, left: 20, right: 20 }}>
            <View style={styles.moreItem} />
            <View style={styles.moreItem} />
            <View style={styles.moreItem} />
          </TouchableOpacity>
        </View>
        <ListView
          enableEmptySections
          dataSource={this.ds.cloneWithRows(this.state.passengers)}
          renderRow={u => (
            <Carpooler
              event={this.props.event}
              refresh={this.props.refresh}
              passengers={this.state.passengers}
              pickedUpUsers={this.state.pickedUpUsers}
              refreshing={this.props.refreshing}
              user={u}
              selfIsDriver={this.state.selfIsDriver}
            />
          )}
        />
        {/* if everyone is pickedUp render 'start driving' button */}
        <Choose>
          <When
            condition={
              this.state.selfIsDriver &&
                !this.props.event.yourRide.rideStarted &&
                this.state.passengers.length > 1 &&
                this.state.pickedUpUsers === this.state.passengers.length - 1
            }>
            <TouchableOpacity
              onPress={() => Alert.alert(
                Platform.OS === 'ios' ? 'Start Ride' : 'Start ride',
                "Are you sure? Just making sure you didn't click this by mistake.",
                [
                  { text: 'Cancel', style: 'cancel' },
                  {
                    text: 'OK',
                    onPress: () => {
                      global.firebaseApp
                        .database()
                        .ref('schools')
                        .child(this.props.event.schoolUID)
                        .child('events')
                        .child(this.props.event.uid)
                        .child('rides')
                        .child(this.props.event.yourRide.uid)
                        .update(
                          {
                            rideStarted: true,
                          },
                          () => {
                            const wazeUrl = `waze://?ll=${this.props.event.location.geometry.location.lat},` +
                              `${this.props.event.location.geometry.location.lng}&z=10&navigate=yes`;
                            maybeOpenURL(wazeUrl, {
                              appName: 'Waze',
                              appStoreId: 'id323229106',
                              playStoreId: 'com.waze',
                            }).catch(err => {
                              this.props.alertWithType(
                                'error',
                                'Error',
                                err.toString(),
                              );
                            });
                          },
                        )
                        .catch(err => {
                          this.props.alertWithType(
                            'error',
                            'Error',
                            err.toString(),
                          );
                        });
                    },
                  },
                ],
              )}>
              <ElevatedView style={styles.startDrivingButton} elevation={4}>
                <Text style={styles.buttonText}>
                  START DRIVING
                </Text>
              </ElevatedView>
            </TouchableOpacity>
          </When>
          <When
            condition={
              this.state.selfIsDriver &&
                this.props.event.yourRide.rideStarted &&
                !this.props.event.yourRide.rideCompleted
            }>
            <TouchableOpacity
              onPress={() => Alert.alert(
                Platform.OS === 'ios' ? 'End Ride' : 'End ride',
                "Are you sure? Just making sure you didn't click this by mistake.",
                [
                  { text: 'Cancel', style: 'cancel' },
                  {
                    text: 'OK',
                    onPress: () => {
                      global.firebaseApp
                        .database()
                        .ref('schools')
                        .child(this.props.event.schoolUID)
                        .child('events')
                        .child(this.props.event.uid)
                        .child('rides')
                        .child(this.props.event.yourRide.uid)
                        .update(
                          {
                            rideCompleted: true,
                          },
                          () => {
                            this.props.alertWithType(
                              'success',
                              'YEET',
                              'Aye you made it!',
                            );
                          },
                        )
                        .catch(err => {
                          this.props.alertWithType(
                            'error',
                            'Error',
                            err.toString(),
                          );
                        });
                    },
                  },
                ],
              )}>
              <ElevatedView style={styles.rideCompleteButton} elevation={4}>
                <Text style={styles.buttonText}>
                  COMPLETE RIDE
                </Text>
              </ElevatedView>
            </TouchableOpacity>
          </When>
          <When
            condition={
              this.state.selfIsDriver && this.state.passengers.length === 1
            }>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              NO PASSENGERS AVAILABLE
            </Text>
          </When>
          <When
            condition={
              this.props.event.yourRide.rideStarted &&
                !this.props.event.yourRide.rideCompleted
            }>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              RIDE IN PROGRESS
            </Text>
          </When>
          <When condition={this.props.event.yourRide.rideCompleted}>
            <Text
              style={{
                fontFamily: 'open-sans-semibold',
                fontSize: 18,
                alignSelf: 'center',
                paddingTop: 16,
              }}>
              RIDE COMPLETED
            </Text>
          </When>
        </Choose>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    paddingVertical: 8,
  },
  label: {
    fontFamily: 'open-sans-semibold',
    fontSize: 12,
    color: 'rgba(128, 128, 128, 0.7)',
  },
  headerRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginHorizontal: 8,
    paddingBottom: 4,
  },
  moreContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    width: 24,
  },
  moreItem: {
    backgroundColor: '#546E7A',
    height: 5,
    width: 5,
    borderRadius: 5,
  },
  startDrivingButton: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    marginHorizontal: 8,
    paddingVertical: 8,
    marginTop: 8,
    backgroundColor: colors.purp,
  },
  rideCompleteButton: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
    marginHorizontal: 8,
    paddingVertical: 8,
    marginTop: 8,
    backgroundColor: colors.neonGreen,
  },
  buttonText: {
    fontFamily: 'open-sans-bold',
    fontSize: 18,
    color: 'white',
  },
});
<|endoftext|>