text:
<?php namespace Bedard\Shop\Models;

use Bedard\Shop\Classes\Driver;
use Carbon\Carbon;
use Model;
use Queue;

/**
 * Cart Model.
 */
class Cart extends Model
{
    /**
     * @var string The database table used by the model.
     */
    public $table = 'bedard_shop_carts';

    /**
     * @var array Default attributes
     */
    public $attributes = [
        'address_id' => null,
        'created_at' => null,
        'id' => null,
        'item_count' => 0,
        'item_total' => 0,
        'token' => null,
        'update_count' => 0,
        'updated_at' => null,
        'user_id' => null,
    ];

    /**
     * @var array Attribute casting
     */
    protected $casts = [
        'update_count' => 'integer',
        'item_count' => 'integer',
        'item_total' => 'float',
    ];

    /**
     * @var array Dates
     */
    protected $dates = [
        'abandoned_at',
        'closed_at',
    ];

    /**
     * @var array Guarded fields
     */
    protected $guarded = ['*'];

    /**
     * @var array Fillable fields
     */
    protected $fillable = [
        'address_id',
        'closed_at',
        'item_count',
        'item_total',
        'update_count',
        'user_id',
    ];

    /**
     * @var array Relations
     */
    public $belongsTo = [
        'address' => [
            'Bedard\Shop\Models\Address',
        ],
        'user' => [
            'RainLab\User\Models\User',
        ],
    ];

    public $belongsToMany = [
        'statuses' => [
            'Bedard\Shop\Models\Status',
            'order' => 'pivot_created_at desc',
            'pivot' => [
                'created_at',
                'driver',
            ],
            'table' => 'bedard_shop_cart_status',
        ],
    ];

    public $hasMany = [
        'items' => [
            'Bedard\Shop\Models\CartItem',
        ],
    ];

    /**
     * Abandon a cart.
     *
     * @return void
     */
    public function abandon()
    {
        $status = Status::isAbandoned()->first();

        if ($status) {
            $this->setStatus($status);
        }

        $this->abandoned_at = Carbon::now();
        $this->save();
    }

    /**
     * Add inventory to the cart.
     *
     * @param  int $inventoryId
     * @param  int $quantity
     */
    public function addInventory($inventoryId, $quantity = 1)
    {
        $item = $this->getItemByInventoryId($inventoryId);

        $item->quantity += $quantity;

        return $this->saveItem($item);
    }

    /**
     * After create.
     *
     * @return void
     */
    public function afterCreate()
    {
        $this->createDefaultStatus();
    }

    /**
     * Before create.
     *
     * @return void
     */
    public function beforeCreate()
    {
        $this->generateToken();
    }

    /**
     * Before save.
     *
     * @return void
     */
    public function beforeSave()
    {
        $this->incrementUpdateCount();
    }

    /**
     * Create the default status.
     *
     * @return void
     */
    protected function createDefaultStatus()
    {
        $status = Status::isDefault()->first();

        if ($status) {
            $this->setStatus($status);
        }
    }

    /**
     * Close a cart.
     *
     * @return bool
     */
    public function close()
    {
        $this->closed_at = Carbon::now();

        return $this->save();
    }

    /**
     * Generate a random token.
     *
     * @return void
     */
    protected function generateToken()
    {
        $this->token = str_random(40);
    }

    /**
     * Get or instantiate an inventory.
     *
     * @param  int $inventoryId
     * @return \Bedard\Shop\Models\Inventory
     */
    public function getItemByInventoryId($inventoryId)
    {
        $inventory = Inventory::findOrFail($inventoryId);

        $item = $this->items()->firstOrNew([
            'cart_id' => $this->id,
            'inventory_id' => $inventoryId,
            'product_id' => $inventory->product_id,
        ]);

        $item->bindEvent('model.beforeSave', function () use ($inventory, $item) {
            if ($item->quantity > $inventory->quantity) {
                $item->quantity = $inventory->quantity;
            }
        });

        return $item;
    }

    /**
     * Get the most recent status.
     *
     * @return \Bedard\Shop\Models\Status
     */
    public function getStatusAttribute()
    {
        return $this->statuses->last();
    }

    /**
     * Increment the update count.
     *
     * @return void
     */
    protected function incrementUpdateCount()
    {
        $this->update_count++;
    }

    /**
     * Process carts that have been abandoned.
     *
     * @return void
     */
    public static function processAbandoned()
    {
        self::isAbandoned()->get()->each(function ($cart) {
            $cart->abandon();
        });
    }

    /**
     * Reduce the available inventory.
     *
     * @return void
     */
    public function reduceAvailableInventory()
    {
        $id = $this->id;
        Queue::push(function ($job) use ($id) {
            $cart = Cart::with('items.inventory')->findOrFail($id);

            $cart->items->each(function ($item) {
                $item->reduceAvailableInventory();
            });
        });
    }

    /**
     * Remove an item from the cart.
     *
     * @param  int                      $itemId
     * @return \Bedard\Shop\Models\CartItem
     */
    public function removeItem($itemId)
    {
        $item = $this->items()
            ->withTrashed()
            ->findOrFail($itemId);

        $item->delete();

        $this->syncItems();

        return $item;
    }

    /**
     * Restock the available inventories.
     *
     * @return void
     */
    public function restockInventories()
    {
        $id = $this->id;
        Queue::push(function ($job) use ($id) {
            $cart = Cart::with('items.inventory')->findOrFail($id);
            $cart->items->each(function ($item) {
                $item->inventory->quantity += $item->quantity;
                $item->inventory->save();
            });
        });
    }

    /**
     * Save an item and sync the cart.
     *
     * @param  \Bedard\Shop\Models\Item     $item
     * @return \Bedard\Shop\Models\Item
     */
    public function saveItem($item)
    {
        $item->save();
        $this->syncItems();

        return $item;
    }

    /**
     * Select abandoned carts.
     *
     * @param  \October\Rain\Database\Builder $query
     * @return \October\Rain\Database\Builder
     */
    public function scopeIsAbandoned($query)
    {
        $lifespan = Settings::getLifespan();

        return $query->where('updated_at', '<', Carbon::now()->subMinutes($lifespan));
    }

    /**
     * Select closed carts.
     *
     * @param  \October\Rain\Database\Builder $query
     * @return \October\Rain\Database\Builder
     */
    public function scopeIsClosed($query)
    {
        return $query->whereNotNull('closed_at');
    }

    /**
     * Select open carts.
     *
     * @param  \October\Rain\Database\Builder $query
     * @return \October\Rain\Database\Builder
     */
    public function scopeIsOpen($query)
    {
        return $query
            ->whereNull('abandoned_at')
            ->whereNull('closed_at');
    }

    /**
     * Set an inventory.
     *
     * @param int $inventoryId
     * @param int $quantity
     */
    public function setInventory($inventoryId, $quantity)
    {
        $item = $this->getItemByInventoryId($inventoryId);

        $item->quantity = $quantity;

        return $this->saveItem($item);
    }

    /**
     * Set a cart status.
     *
     * @param \Bedard\Shop\Models\Status        $status
     * @param \Bedard\Shop\Classes\Driver|null  $driver
     */
    public function setStatus(Status $status, Driver $driver = null)
    {
        $this->statuses()->attach($status, [
            'driver' => $driver ? get_class($driver) : null,
        ]);

        // reduce inventories if neccessary
        if ($status->is_reducing) {
            $id = $this->id;
            Queue::push(function () use ($id) {
                $cart = Cart::findOrFail($id);
                $cart->reduceAvailableInventory();
            });
        }
    }

    /**
     * Sync the item_count and item_total columns.
     *
     * @return void
     */
    public function syncItems()
    {
        $total = 0;
        $this->load('items.inventory.product');

        foreach ($this->items as $item) {
            $total += $item->quantity * $item->product->base_price;
        }

        $this->item_total = $total;
        $this->item_count = $this->items()->sum('quantity') ?: 0;

        $this->save();
    }
}


text: package "vsftpd"

redpajama_set_name: RedPajamaGithub


text:
Puppet::Type.newtype(:consul_policy) do
  desc <<-'EOD'
  Manages a Consul ACL policy
  EOD
  ensurable

  newparam(:name, namevar: true) do
    desc 'Name of the policy'
    validate do |value|
      raise ArgumentError, 'Policy name must be a string' unless value.is_a?(String)
    end
  end

  newproperty(:id) do
    desc 'ID of already existing policy'
    validate do |value|
      raise ArgumentError, 'ID must be a string' unless value.is_a?(String)
    end

    defaultto ''
  end

  newproperty(:description) do
    desc 'Description of the policy'
    validate do |value|
      raise ArgumentError, 'Description must be a string' unless value.is_a?(String)
    end
  end

  newproperty(:datacenters, array_matching: :all) do
    desc 'List of datacenter names assigned to the policy'
    validate do |value|
      raise ArgumentError, 'Datacenter name list must be an array of strings' unless value.is_a?(String)
    end

    defaultto []
  end

  newproperty(:rules, array_matching: :all) do
    desc 'List of ACL rules for this policy'
    validate do |value|
      raise ArgumentError, 'Policy rule must be a hash' unless value.is_a?(Hash)

      raise ArgumentError, 'Policy rule needs to specify a resource' unless value.key?('resource')
      raise ArgumentError, 'Policy rule needs to specify a segment' unless value.key?('segment') || ['acl', 'operator', 'keyring'].include?(value['resource'])
      raise ArgumentError, 'Policy rule needs to specify a disposition' unless value.key?('disposition')

      raise ArgumentError, 'Policy rule resource must be a string' unless value['resource'].is_a?(String)
      raise ArgumentError, 'Policy rule segment must be a string' unless value['segment'].is_a?(String) || ['acl', 'operator', 'keyring'].include?(value['resource'])
      raise ArgumentError, 'Policy rule disposition must be a string' unless value['disposition'].is_a?(String)
    end

    defaultto []
  end

  newparam(:acl_api_token) do
    desc 'Token for accessing the ACL API'
    validate do |value|
      raise ArgumentError, 'ACL API token must be a string' unless value.is_a?(String)
    end
    defaultto ''
  end

  newparam(:protocol) do
    desc 'consul protocol'
    newvalues(:http, :https)
    defaultto :http
  end

  newparam(:port) do
    desc 'consul port'
    defaultto 8500
    validate do |value|
      raise ArgumentError, 'The port number must be a number' unless value.is_a?(Integer)
    end
  end

  newparam(:hostname) do
    desc 'consul hostname'
    validate do |value|
      raise ArgumentError, 'The hostname must be a string' unless value.is_a?(String)
    end
    defaultto 'localhost'
  end

  newparam(:api_tries) do
    desc 'number of tries when contacting the Consul REST API'
    defaultto 3
    validate do |value|
      raise ArgumentError, 'Number of API tries must be a number' unless value.is_a?(Integer)
    end
  end

  autorequire(:service) do
    ['consul']
  end
end


text:
// --------------------------------------------------------------------------------------------------
//  Copyright (c) 2016 Microsoft Corporation
//
//  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.
// --------------------------------------------------------------------------------------------------

package com.microsoft.Malmo.MissionHandlers;

import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;

import com.google.gson.JsonObject;
import com.microsoft.Malmo.MissionHandlerInterfaces.IObservationProducer;
import com.microsoft.Malmo.Schemas.MissionInit;
import com.microsoft.Malmo.Schemas.NamedPoint;
import com.microsoft.Malmo.Schemas.ObservationFromDistance;
import com.microsoft.Malmo.Utils.PositionHelper;

/** Simple IObservationProducer class that creates a single "distanceFromTarget" observation, using the target specified in the MissionInit XML.<br>
 * (Yes, we know this is cheating for RL, but it's a useful test example.)
 */
public class ObservationFromDistanceImplementation extends HandlerBase implements IObservationProducer
{
	private ObservationFromDistance odparams;

	@Override
	public boolean parseParameters(Object params)
	{
		if (params == null || !(params instanceof ObservationFromDistance))
			return false;

		this.odparams = (ObservationFromDistance)params;
		return true;
	}

	@Override
	public void writeObservationsToJSON(JsonObject json, MissionInit missionInit)
	{
		for (NamedPoint marker : odparams.getMarker())
		{
			EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
			json.addProperty("distanceFrom" + makeSafe(marker.getName()), PositionHelper.calcDistanceFromPlayerToPosition(player, marker));
    	}
	}

	private String makeSafe(String raw)
	{
		// Hopefully the string won't be too crazy, since the XSD:Name type will disallow bonkers characters.
		// Just trim any whitespace.
		return raw.trim();
	}
	@Override
	public void prepare(MissionInit missionInit) {}

	@Override
	public void cleanup() {}
}


text:
package org.camunda.bpm.spring.boot.starter.event;

import org.camunda.bpm.engine.ProcessEngine;

public class PreUndeployEvent {

  private final ProcessEngine processEngine;

  public PreUndeployEvent(ProcessEngine processEngine) {
    this.processEngine = processEngine;
  }

  public ProcessEngine getProcessEngine() {
    return processEngine;
  }

  @Override
  public String toString() {
    return "PreUndeployEvent{" +
      "processEngine=" + processEngine +
      '}';
  }
}


text:
print "Enter the path to the .ics file"
file = input()
file = open(file, "rt")
print "Enter the Course ID and Course Number (i.e. THEO 111) (The caps matter)"
course = input()
print "Enter the desired start time in 24 hour format like this: '152300', meaning 3:23 PM"
time = input()
print "Enter the desired end time in the same format"
endTime = input()
calendarString = file.read()
file.close()
#make the strings into a list so that it can be worked with
calendarList = []
for x in range(0, len(calendarString) - 1):
	calendarList.append(calendarString[x])
timeList = []
for x in range(0, len(time)):
	timeList.append(time[x])
endTimeList = []
for x in range(0, len(endTime)):
	endTimeList.append(endTime[x])
#go through the whole file, and find each instance of the class in question
#after the class and time are found, the current time is replaced with the desired time
endLocation = 0
while calendarString.find(course, endLocation) != -1:
	classLocation = calendarString.find(course, endLocation)
	startDateLocation = calendarString.find("DTSTART:", classLocation)
	startTimeLocation = calendarString.find("T", startDateLocation + 7) + 1
	for i in range(startTimeLocation, startTimeLocation + 5):
		calendarList[i] = timeList[i - startTimeLocation]
		endLocation = i
	endDateLocation = calendarString.find("DTEND:", endLocation)
	endTimeLocation = calendarString.find("T", endDateLocation) + 1
	for i in range(endTimeLocation, endTimeLocation + 5):
		calendarList[i] = endTimeList[i - endTimeLocation]
		endLocation = i

#write the changes you've made to the list to a string, then to a file
outFile = "fixed-schedule.ics"
outFile = open(outFile, "wt")
newCalendarString = " "
for y in range(0, len(calendarString) - 1):
	newCalendarString = newCalendarString + calendarList[y]
outFile.write(newCalendarString)
outFile.close()

print "complete"


text:
import type { Locale } from '../types'
import formatDistance from './_lib/formatDistance/index'
import formatLong from './_lib/formatLong/index'
import formatRelative from './_lib/formatRelative/index'
import localize from './_lib/localize/index'
import match from './_lib/match/index'

/**
 * @type {Locale}
 * @category Locales
 * @summary Italian locale.
 * @language Italian
 * @iso-639-2 ita
 * @author Alberto Restifo [@albertorestifo]{@link https://github.com/albertorestifo}
 * @author Giovanni Polimeni [@giofilo]{@link https://github.com/giofilo}
 * @author Vincenzo Carrese [@vin-car]{@link https://github.com/vin-car}
 */
const locale: Locale = {
  code: 'it',
  formatDistance: formatDistance,
  formatLong: formatLong,
  formatRelative: formatRelative,
  localize: localize,
  match: match,
  options: {
    weekStartsOn: 1 /* Monday */,
    firstWeekContainsDate: 4,
  },
}

export default locale


text:
#include "join_hash.hpp"

#include <cmath>
#include <memory>
#include <numeric>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

#include "bytell_hash_map.hpp"
#include "hyrise.hpp"
#include "join_hash/join_hash_steps.hpp"
#include "join_hash/join_hash_traits.hpp"
#include "join_helper/join_output_writing.hpp"
#include "scheduler/abstract_task.hpp"
#include "scheduler/job_task.hpp"
#include "type_comparison.hpp"
#include "utils/assert.hpp"
#include "utils/format_duration.hpp"
#include "utils/timer.hpp"

namespace hyrise {

bool JoinHash::supports(const JoinConfiguration config) {
  // JoinHash supports only equi joins and every join mode, except FullOuter.
  // Secondary predicates in AntiNullAsTrue are not supported, because implementing them is cumbersome and we couldn't
  // so far determine a case/query where we'd need them.
  return config.predicate_condition == PredicateCondition::Equals && config.join_mode != JoinMode::FullOuter &&
         (config.join_mode != JoinMode::AntiNullAsTrue || !config.secondary_predicates);
}

JoinHash::JoinHash(const std::shared_ptr<const AbstractOperator>& left,
                   const std::shared_ptr<const AbstractOperator>& right, const JoinMode mode,
                   const OperatorJoinPredicate& primary_predicate,
                   const std::vector<OperatorJoinPredicate>& secondary_predicates,
                   const std::optional<size_t>& radix_bits)
    : AbstractJoinOperator(OperatorType::JoinHash, left, right, mode, primary_predicate, secondary_predicates,
                           std::make_unique<PerformanceData>()),
      _radix_bits(radix_bits) {}

const std::string& JoinHash::name() const {
  static const auto name = std::string{"JoinHash"};
  return name;
}

std::shared_ptr<AbstractOperator> JoinHash::_on_deep_copy(
    const std::shared_ptr<AbstractOperator>& copied_left_input,
    const std::shared_ptr<AbstractOperator>& copied_right_input,
    std::unordered_map<const AbstractOperator*, std::shared_ptr<AbstractOperator>>& copied_ops) const {
  return std::make_shared<JoinHash>(copied_left_input, copied_right_input, _mode, _primary_predicate,
                                    _secondary_predicates, _radix_bits);
}

void JoinHash::_on_set_parameters(const std::unordered_map<ParameterID, AllTypeVariant>& parameters) {}

size_t JoinHash::calculate_radix_bits(const size_t build_side_size, const size_t probe_side_size, const JoinMode mode) {
  /*
    The number of radix bits is used to determine the number of build partitions. The idea is to size the partitions in
    a way that keeps the whole hash map cache resident. We aim for the largest unshared cache (for most Intel systems
    that's the L2 cache, for Apple's M1 the L1 cache). This calculation should include hardware knowledge, once
    available in Hyrise. As of now, we assume a cache size of 1024 KB, of which we use 75 %.

    We estimate the size the following way:
      - we assume each key appears once (that is an overestimation space-wise, but we
        aim rather for a hash map that is slightly smaller than the cache than slightly larger)
      - each entry in the hash map is a pair of the actual hash key and the SmallPosList storing uint32_t offsets (see
        hash_join_steps.hpp)
  */
  if (build_side_size > probe_side_size) {
    /*
      Hash joins perform best when the build side is small. For inner joins, we can simply select the smaller input
      table as the build side. For other joins, such as semi or outer joins, the build side is fixed. In this case,
      other join operators might be more efficient. We emit performance warning in this case. In the future, the
      optimizer could identify these cases of potentially inefficient hash joins and switch to other join algorithms.
    */
    PerformanceWarning("Build side larger than probe side in hash join");
  }

  // We assume a cache of 1024 KB for an Intel Xeon Platinum 8180. For local deployments or other CPUs, this size might
  // be different (e.g., an AMD EPYC 7F72 CPU has an L2 cache size of 512 KB and Apple's M1 has 128 KB).
  constexpr auto L2_CACHE_SIZE = 1'024'000;                   // bytes
  constexpr auto L2_CACHE_MAX_USABLE = L2_CACHE_SIZE * 0.75;  // use 75% of the L2 cache size

  // For information about the sizing of the bytell hash map, see the comments:
  // https://probablydance.com/2018/05/28/a-new-fast-hash-table-in-response-to-googles-new-fast-hash-table/
  // Bytell hash map has a maximum fill factor of 0.9375. Since it's hard to estimate the number of distinct values in
  // a radix partition (and thus the size of each hash table), we accomodate a little bit extra space for
  // slightly skewed data distributions and aim for a fill level of 80%.
  const auto complete_hash_map_size =
      // number of items in map
      static_cast<double>(build_side_size) *
      // key + value (and one byte overhead, see link above)
      static_cast<double>(sizeof(uint32_t)) / 0.8;

  const auto cluster_count = std::max(1.0, complete_hash_map_size / L2_CACHE_MAX_USABLE);

  return static_cast<size_t>(std::ceil(std::log2(cluster_count)));
}

std::shared_ptr<const Table> JoinHash::_on_execute() {
  Assert(supports({_mode, _primary_predicate.predicate_condition,
                   left_input_table()->column_data_type(_primary_predicate.column_ids.first),
                   right_input_table()->column_data_type(_primary_predicate.column_ids.second),
                   !_secondary_predicates.empty(), left_input_table()->type(), right_input_table()->type()}),
         "JoinHash doesn't support these parameters");

  std::shared_ptr<const Table> build_input_table;
  std::shared_ptr<const Table> probe_input_table;
  auto build_column_id = ColumnID{};
  auto probe_column_id = ColumnID{};

  /**
   * The hash join works best when the table being probed is larger than the side for which the hash table is built
   * (i.e., the build side). As consequence, when we are to freely determine the build side, we chose the smaller
   * input table. For other cases, we cannot freely decide.
   *
   * Build and probe side are assigned as follows:
   *   JoinMode::Inner        The smaller table becomes the build side, the bigger the probe side
   *   JoinMode::Left/Right   The outer table becomes the probe side, the inner table becomes the build side
   *   JoinMode::FullOuter    Not supported by JoinHash
   *   JoinMode::Semi/Anti*   The left table becomes the probe side, the right table becomes the build side
   */
  const auto build_hash_table_for_right_input =
      _mode == JoinMode::Left || _mode == JoinMode::AntiNullAsTrue || _mode == JoinMode::AntiNullAsFalse ||
      _mode == JoinMode::Semi ||
      (_mode == JoinMode::Inner && _left_input->get_output()->row_count() > _right_input->get_output()->row_count());

  if (build_hash_table_for_right_input) {
    // We don't have to swap the operation itself here, because we only support the commutative Equi Join.
    build_input_table = _right_input->get_output();
    probe_input_table = _left_input->get_output();
    build_column_id = _primary_predicate.column_ids.second;
    probe_column_id = _primary_predicate.column_ids.first;
  } else {
    build_input_table = _left_input->get_output();
    probe_input_table = _right_input->get_output();
    build_column_id = _primary_predicate.column_ids.first;
    probe_column_id = _primary_predicate.column_ids.second;
  }

  // If the input operators are swapped, we also have to swap the column pairs and the predicate conditions
  // of the secondary join predicates.
  auto adjusted_secondary_predicates = _secondary_predicates;

  if (build_hash_table_for_right_input) {
    for (auto& predicate : adjusted_secondary_predicates) {
      predicate.flip();
    }
  }

  auto adjusted_column_ids = std::make_pair(build_column_id, probe_column_id);

  const auto build_column_type = build_input_table->column_data_type(build_column_id);
  const auto probe_column_type = probe_input_table->column_data_type(probe_column_id);

  // Depending on which input table became the build/probe table we have to order the columns of the output table.
  // Semi/Anti* Joins only emit tuples from the probe table, which is given by the right input table in Hyrise.
  // For other join modes, we need to check which side has been chosen as the probe side (see variable
  // `build_hash_table_for_right_input` for more details).
  auto output_column_order = OutputColumnOrder{};
  if (_mode == JoinMode::Semi || _mode == JoinMode::AntiNullAsTrue || _mode == JoinMode::AntiNullAsFalse) {
    output_column_order = OutputColumnOrder::RightOnly;
  } else if (build_hash_table_for_right_input) {
    output_column_order = OutputColumnOrder::RightFirstLeftSecond;
  } else {
    output_column_order = OutputColumnOrder::LeftFirstRightSecond;
  }

  auto& join_hash_performance_data = dynamic_cast<PerformanceData&>(*performance_data);
  resolve_data_type(build_column_type, [&](const auto build_data_type_t) {
    using BuildColumnDataType = typename decltype(build_data_type_t)::type;
    resolve_data_type(probe_column_type, [&](const auto probe_data_type_t) {
      using ProbeColumnDataType = typename decltype(probe_data_type_t)::type;

      constexpr auto BOTH_ARE_STRING =
          std::is_same_v<pmr_string, BuildColumnDataType> && std::is_same_v<pmr_string, ProbeColumnDataType>;
      constexpr auto NEITHER_IS_STRING =
          !std::is_same_v<pmr_string, BuildColumnDataType> && !std::is_same_v<pmr_string, ProbeColumnDataType>;

      if constexpr (BOTH_ARE_STRING || NEITHER_IS_STRING) {
        if (!_radix_bits) {
          _radix_bits = calculate_radix_bits(build_input_table->row_count(), probe_input_table->row_count(), _mode);
        }

        // It needs to be ensured that the build partitions do not get too large, because the used offsets in the
        // hash maps might otherwise overflow. Since radix partitioning aims to avoid large build partitions, this
        // should never happen. Nonetheless, we better assert since the effects of overflows will probably be hard to
        // debug.
        const auto max_partition_size = std::numeric_limits<uint32_t>::max() * 0.5;
        Assert(static_cast<uint32_t>(static_cast<double>(build_input_table->row_count()) / std::pow(2, *_radix_bits)) <
                   max_partition_size,
               "Partition count too small (potential overflows in hash map offsetting).");

        _impl = std::make_unique<JoinHashImpl<BuildColumnDataType, ProbeColumnDataType>>(
            *this, build_input_table, probe_input_table, _mode, adjusted_column_ids,
            _primary_predicate.predicate_condition, output_column_order, *_radix_bits, join_hash_performance_data,
            adjusted_secondary_predicates);
      } else {
        Fail("Cannot join String with non-String column");
      }
    });
  });

  Assert(_radix_bits, "Radix bits are not set.");
  join_hash_performance_data.radix_bits = *_radix_bits;
  join_hash_performance_data.left_input_is_build_side = !build_hash_table_for_right_input;

  return _impl->_on_execute();
}

void JoinHash::_on_cleanup() {
  _impl.reset();
}

template <typename BuildColumnType, typename ProbeColumnType>
class JoinHash::JoinHashImpl : public AbstractReadOnlyOperatorImpl {
 public:
  JoinHashImpl(const JoinHash& join_hash, const std::shared_ptr<const Table>& build_input_table,
               const std::shared_ptr<const Table>& probe_input_table, const JoinMode mode,
               const ColumnIDPair& column_ids, const PredicateCondition predicate_condition,
               const OutputColumnOrder output_column_order, const size_t radix_bits,
               JoinHash::PerformanceData& performance_data, std::vector<OperatorJoinPredicate>& secondary_predicates)
      : _join_hash(join_hash),
        _build_input_table(build_input_table),
        _probe_input_table(probe_input_table),
        _mode(mode),
        _column_ids(column_ids),
        _predicate_condition(predicate_condition),
        _performance_data(performance_data),
        _output_column_order(output_column_order),
        _secondary_predicates(secondary_predicates),
        _radix_bits(radix_bits) {}

 protected:
  const JoinHash& _join_hash;
  const std::shared_ptr<const Table> _build_input_table, _probe_input_table;
  const JoinMode _mode;
  const ColumnIDPair _column_ids;
  const PredicateCondition _predicate_condition;
  JoinHash::PerformanceData& _performance_data;

  OutputColumnOrder _output_column_order;

  const std::vector<OperatorJoinPredicate>& _secondary_predicates;

  std::shared_ptr<Table> _output_table;

  const size_t _radix_bits;

  // Determine correct type for hashing
  using HashedType = typename JoinHashTraits<BuildColumnType, ProbeColumnType>::HashType;

  std::shared_ptr<const Table> _on_execute() override {
    /**
     * Keep/Discard NULLs from build and probe columns as follows
     *
     * JoinMode::Inner              Discard NULLs from both columns
     * JoinMode::Left/Right         Discard NULLs from the build column (the inner table), but keep them on the probe
     *                              column (the outer table)
     * JoinMode::FullOuter          Not supported by JoinHash
     * JoinMode::Semi               Discard NULLs from both columns
     * JoinMode::AntiNullAsFalse    Discard NULLs from the build column (the right table), but keep them on the probe
     *                              column (the left table)
     * JoinMode::AntiNullAsTrue     Keep NULLs from both columns
     */

    const auto keep_nulls_build_column = _mode == JoinMode::AntiNullAsTrue;
    const auto keep_nulls_probe_column = _mode == JoinMode::Left || _mode == JoinMode::Right ||
                                         _mode == JoinMode::AntiNullAsTrue || _mode == JoinMode::AntiNullAsFalse;

    // Containers used to store histograms for (potentially subsequent) radix partitioning step (in cases
    // _radix_bits > 0). Created during materialization step.
    std::vector<std::vector<size_t>> histograms_build_column;
    std::vector<std::vector<size_t>> histograms_probe_column;

    // Output containers of materialization step. Uses the same output type as the radix partitioning step to allow
    // shortcut for _radix_bits == 0 (in this case, we can skip the partitioning altogether).
    RadixContainer<BuildColumnType> materialized_build_column;
    RadixContainer<ProbeColumnType> materialized_probe_column;

    // Containers for potential (skipped when build side small) radix partitioning step
    RadixContainer<BuildColumnType> radix_build_column;
    RadixContainer<ProbeColumnType> radix_probe_column;

    // HashTables for the build column, one for each partition
    std::vector<std::optional<PosHashTable<HashedType>>> hash_tables;

    /**
     * Depiction of the hash join parallelization (radix partitioning can be skipped when radix_bits = 0)
     * ===============================================================================================
     * We have two data paths, one for build side and one for probe input side. All tasks might spawn concurrent tasks
     * tasks themselves. For example, materialize parallelizes over the input chunks and the following steps over the
     * radix clusters.
     *
     * Bloom filters can be used to skip rows that will not find a join partner. They are not shown here.
     *
     *            Build Table                          Probe Table
     *                 |                                    |
     *        materialize_input()                  materialize_input()
     *                 |                                    |
     *      ( partition_by_radix() )            ( partition_by_radix() )
     *                 |                                    |
     *               build()                                |
     *                   \_                               _/
     *                     \_                           _/
     *                       \_                       _/
     *                         \_                   _/
     *                           \                 /
     *                          Probing (actual Join)
     */

    /**
     * 1.1. Materialize the build partition, which is expected to be smaller. Create a Bloom filter.
     */

    auto build_side_bloom_filter = BloomFilter{};
    auto probe_side_bloom_filter = BloomFilter{};

    const auto materialize_build_side = [&](const auto& input_bloom_filter) {
      if (keep_nulls_build_column) {
        materialized_build_column = materialize_input<BuildColumnType, HashedType, true>(
            _build_input_table, _column_ids.first, histograms_build_column, _radix_bits, build_side_bloom_filter,
            input_bloom_filter);
      } else {
        materialized_build_column = materialize_input<BuildColumnType, HashedType, false>(
            _build_input_table, _column_ids.first, histograms_build_column, _radix_bits, build_side_bloom_filter,
            input_bloom_filter);
      }
    };

    /**
     * 1.2. Materialize the larger probe partition. Use the Bloom filter from the probe partition to skip rows that
     *       will not find a join partner.
     */
    const auto materialize_probe_side = [&](const auto& input_bloom_filter) {
      if (keep_nulls_probe_column) {
        materialized_probe_column = materialize_input<ProbeColumnType, HashedType, true>(
            _probe_input_table, _column_ids.second, histograms_probe_column, _radix_bits, probe_side_bloom_filter,
            input_bloom_filter);
      } else {
        materialized_probe_column = materialize_input<ProbeColumnType, HashedType, false>(
            _probe_input_table, _column_ids.second, histograms_probe_column, _radix_bits, probe_side_bloom_filter,
            input_bloom_filter);
      }
    };

    Timer timer_materialization;
    if (_build_input_table->row_count() < _probe_input_table->row_count()) {
      // When materializing the first side (here: the build side), we do not yet have a Bloom filter. To keep the number
      // of code paths low, materialize_*_side always expects a Bloom filter. For the first step, we thus pass in a
      // Bloom filter that returns true for every probe.
      materialize_build_side(ALL_TRUE_BLOOM_FILTER);
      _performance_data.set_step_runtime(OperatorSteps::BuildSideMaterializing, timer_materialization.lap());
      materialize_probe_side(build_side_bloom_filter);
      _performance_data.set_step_runtime(OperatorSteps::ProbeSideMaterializing, timer_materialization.lap());
    } else {
      // Here, we first materialize the probe side and use the resulting Bloom filter in the materialization of the
      // build side. Consequently, the Bloom filter later passed into build() will have no effect as it has already
      // been used here to filter non-matching values.
      materialize_probe_side(ALL_TRUE_BLOOM_FILTER);
      _performance_data.set_step_runtime(OperatorSteps::ProbeSideMaterializing, timer_materialization.lap());
      materialize_build_side(probe_side_bloom_filter);
      _performance_data.set_step_runtime(OperatorSteps::BuildSideMaterializing, timer_materialization.lap());
    }

    // Store the number of materialized values. Depending on the order of materialization (which depends on the input
    // sizes), each side might or might not be filtered by the Bloom filter.
    for (const auto& partition : materialized_build_column) {
      _performance_data.build_side_materialized_value_count += partition.elements.size();
    }
    for (const auto& partition : materialized_probe_column) {
      _performance_data.probe_side_materialized_value_count += partition.elements.size();
    }

    /**
     * 2. Perform radix partitioning for build and probe sides. The Bloom filters are not used in this step. Future work
     *    could use them on the build side to exclude them for values that are not seen on the probe side. That would
     *    reduce the size of the intermediary results, but would require an adapted calculation of the output offsets
     *    within partition_by_radix.
     */
    if (_radix_bits > 0) {
      Timer timer_clustering;
      auto jobs = std::vector<std::shared_ptr<AbstractTask>>{};

      jobs.emplace_back(std::make_shared<JobTask>([&]() {
        // radix partition the build table
        if (keep_nulls_build_column) {
          radix_build_column = partition_by_radix<BuildColumnType, HashedType, true>(
              materialized_build_column, histograms_build_column, _radix_bits);
        } else {
          radix_build_column = partition_by_radix<BuildColumnType, HashedType, false>(
              materialized_build_column, histograms_build_column, _radix_bits);
        }

        // After the data in materialized_build_column has been partitioned, it is not needed anymore.
        materialized_build_column.clear();
      }));

      jobs.emplace_back(std::make_shared<JobTask>([&]() {
        // radix partition the probe column.
        if (keep_nulls_probe_column) {
          radix_probe_column = partition_by_radix<ProbeColumnType, HashedType, true>(
              materialized_probe_column, histograms_probe_column, _radix_bits);
        } else {
          radix_probe_column = partition_by_radix<ProbeColumnType, HashedType, false>(
              materialized_probe_column, histograms_probe_column, _radix_bits);
        }

        // After the data in materialized_probe_column has been partitioned, it is not needed anymore.
        materialized_probe_column.clear();
      }));

      Hyrise::get().scheduler()->schedule_and_wait_for_tasks(jobs);

      histograms_build_column.clear();
      histograms_probe_column.clear();

      _performance_data.set_step_runtime(OperatorSteps::Clustering, timer_clustering.lap());
    } else {
      // short cut: skip radix partitioning and use materialized data directly
      radix_build_column = std::move(materialized_build_column);
      radix_probe_column = std::move(materialized_probe_column);
    }

    /**
     * 3. Build hash tables.
     *    In the case of semi or anti joins, we do not need to track all rows on the hashed side, just one per value.
     *    value. However, if we have secondary predicates, those might fail on that single row. In that case, we DO need
     *    all rows.
     *    We use the probe side's Bloom filter to exclude values from the hash table that will not be accessed in the
     *    probe step.
     */
    Timer timer_hash_map_building;
    if (_secondary_predicates.empty() &&
        (_mode == JoinMode::Semi || _mode == JoinMode::AntiNullAsTrue || _mode == JoinMode::AntiNullAsFalse)) {
      hash_tables = build<BuildColumnType, HashedType>(radix_build_column, JoinHashBuildMode::ExistenceOnly,
                                                       _radix_bits, probe_side_bloom_filter);
    } else {
      hash_tables = build<BuildColumnType, HashedType>(radix_build_column, JoinHashBuildMode::AllPositions, _radix_bits,
                                                       probe_side_bloom_filter);
    }
    _performance_data.set_step_runtime(OperatorSteps::Building, timer_hash_map_building.lap());

    // Store the element counts of the built hash tables. Depending on the Bloom filter, we might have significantly
    // less values stored than in the initial input table.
    for (const auto& hash_table : hash_tables) {
      if (!hash_table) {
        continue;
      }

      _performance_data.hash_tables_distinct_value_count += hash_table->distinct_value_count();
      const auto position_count = hash_table->position_count();
      if (position_count) {
        // Update or set hash_tables_position_count if hash table stores positions.
        _performance_data.hash_tables_position_count =
            _performance_data.hash_tables_position_count.value_or(0) + *position_count;
      }
    }

    /**
     * Short cut for AntiNullAsTrue:
     *   If there is any NULL value on the build side, do not bother probing as no tuples can be emitted anyway (as
     *   long as JoinHash/AntiNullAsTrue doesn't support secondary predicates). Doing this early out right here is
     *   hacky, but during probing we assume NULL values on the build side do not matter, so we'd have no chance
     *   detecting a NULL value on the build side there.
     */
    if (_mode == JoinMode::AntiNullAsTrue) {
      for (const auto& build_side_partition : radix_build_column) {
        for (const auto null_value : build_side_partition.null_values) {
          if (null_value) {
            Timer timer_output_writing;
            const auto result = _join_hash._build_output_table({});
            _performance_data.set_step_runtime(OperatorSteps::OutputWriting, timer_output_writing.lap());
            return result;
          }
        }
      }
    }

    radix_build_column.clear();

    /**
     * 4. Probe step
     */
    std::vector<RowIDPosList> build_side_pos_lists;
    std::vector<RowIDPosList> probe_side_pos_lists;
    const size_t partition_count = radix_probe_column.size();
    build_side_pos_lists.resize(partition_count);
    probe_side_pos_lists.resize(partition_count);

    // simple heuristic: half of the rows of the probe side will match
    const size_t result_rows_per_partition =
        _probe_input_table->row_count() > 0 ? _probe_input_table->row_count() / partition_count / 2 : 0;
    for (auto partition_index = size_t{0}; partition_index < partition_count; ++partition_index) {
      build_side_pos_lists[partition_index].reserve(result_rows_per_partition);
      probe_side_pos_lists[partition_index].reserve(result_rows_per_partition);
    }

    Timer timer_probing;
    switch (_mode) {
      case JoinMode::Inner:
        probe<ProbeColumnType, HashedType, false>(radix_probe_column, hash_tables, build_side_pos_lists,
                                                  probe_side_pos_lists, _mode, *_build_input_table, *_probe_input_table,
                                                  _secondary_predicates);
        break;

      case JoinMode::Left:
      case JoinMode::Right:
        probe<ProbeColumnType, HashedType, true>(radix_probe_column, hash_tables, build_side_pos_lists,
                                                 probe_side_pos_lists, _mode, *_build_input_table, *_probe_input_table,
                                                 _secondary_predicates);
        break;

      case JoinMode::Semi:
        probe_semi_anti<ProbeColumnType, HashedType, JoinMode::Semi>(radix_probe_column, hash_tables,
                                                                     probe_side_pos_lists, *_build_input_table,
                                                                     *_probe_input_table, _secondary_predicates);
        break;

      case JoinMode::AntiNullAsTrue:
        probe_semi_anti<ProbeColumnType, HashedType, JoinMode::AntiNullAsTrue>(
            radix_probe_column, hash_tables, probe_side_pos_lists, *_build_input_table, *_probe_input_table,
            _secondary_predicates);
        break;

      case JoinMode::AntiNullAsFalse:
        probe_semi_anti<ProbeColumnType, HashedType, JoinMode::AntiNullAsFalse>(
            radix_probe_column, hash_tables, probe_side_pos_lists, *_build_input_table, *_probe_input_table,
            _secondary_predicates);
        break;

      default:
        Fail("JoinMode not supported by JoinHash");
    }
    _performance_data.set_step_runtime(OperatorSteps::Probing, timer_probing.lap());

    radix_probe_column.clear();
    hash_tables.clear();

    /**
     * 5. Write output Table
     */

    /**
     * After the probe step build_side_pos_lists and probe_side_pos_lists contain all pairs of joined rows grouped by
     * partition. Let p be a partition index and r a row index. The value of build_side_pos_lists[p][r] will match
     * probe_side_pos_lists[p][r].
     */

    Timer timer_output_writing;

    const auto create_left_side_pos_lists_by_segment =
        (_build_input_table->type() == TableType::References && _output_column_order != OutputColumnOrder::RightOnly);
    const auto create_right_side_pos_lists_by_segment = (_probe_input_table->type() == TableType::References);

    // A hash join's input can be heavily pre-filtered or the join results in very few matches. To counteract this the
    // partitions can be merged (#2202).
    constexpr auto ALLOW_PARTITION_MERGE = true;
    auto output_chunks =
        write_output_chunks(build_side_pos_lists, probe_side_pos_lists, _build_input_table, _probe_input_table,
                            create_left_side_pos_lists_by_segment, create_right_side_pos_lists_by_segment,
                            _output_column_order, ALLOW_PARTITION_MERGE);

    _performance_data.set_step_runtime(OperatorSteps::OutputWriting, timer_output_writing.lap());

    return _join_hash._build_output_table(std::move(output_chunks));
  }
};

void JoinHash::PerformanceData::output_to_stream(std::ostream& stream, DescriptionMode description_mode) const {
  OperatorPerformanceData<OperatorSteps>::output_to_stream(stream, description_mode);

  const auto separator = (description_mode == DescriptionMode::SingleLine ? ' ' : '\n');
  stream << separator << "Radix bits: " << radix_bits << ".";
  stream << separator << "Build side is " << (left_input_is_build_side ? "left." : "right.");
}

}  // namespace hyrise


text:
package elephantdb.cascading;

import cascading.tuple.Tuple;
import elephantdb.document.KeyValDocument;

/** User: sritchie Date: 12/16/11 Time: 12:08 AM */
public class KeyValGateway implements Gateway<KeyValDocument> {
    public KeyValDocument fromTuple(Tuple tuple) {
        Object key = tuple.getObject(1);
        Object val = tuple.getObject(2);

        return new KeyValDocument<Object, Object>(key, val);
    }

    public Tuple toTuple(KeyValDocument document) {
        return new Tuple(document.key, document.value);
    }
}


text:
function product = setCrossProduct(sets, dim, product)
% setCrossProduct: Build the cross product of a bunch of sets of numbers.
%
%   product = setCrossProduct(sets, dim, product)
%
% Generates a bunch of output sets (rows) each of which contains one element
% from each input set.  The entire set of output sets includes all
% combinations of input elements.
%
% Input Parameters:
%
%   sets: Column cell vector.  Each element is an input set: a vector of
%   numbers.
%
%   dim: Current dimension which is being constructed.  Used only during
%   recursion.  User should leave out this parameter.
%
%   product: The partially constructed output sets.  Used only during
%   recursion.  Users should leave out this parameter.
%
% Output Parameters:
%
%   product: A 2D array containing the output sets as rows.

% Copyright 2007 Ian M. Mitchell (mitchell@cs.ubc.ca).
% This software is used, copied and distributed under the licensing
%   agreement contained in the file LICENSE in the top directory of
%   the distribution.
%
% Created by Ian Mitchell 2007-01-18 as part of JSC 2007 submission.
% Moved 2008-08-05 to a separate file.
% $Date: 2008-08-05 10:39:10 -0700 (Tue, 05 Aug 2008) $
% $Id: setCrossProduct.m 20 2008-08-05 17:39:10Z mitchell $

  if(nargin < 3)
    dim = 1;
    product = zeros(1,0);
  end

  if(dim <= length(sets))
    old_product_size = size(product, 1);
    new_set_size = length(sets{dim});

    % Copy the current product into an array big enough to hold the
    % product with the next set.
    new_product = [ repmat(product, new_set_size, 1), ...
                    zeros(old_product_size * new_set_size, 1) ];

    % Copy in the members of the next set.
    for i = 1 : new_set_size
      interval = (i-1)*old_product_size+1:i*old_product_size;
      new_product(interval, end) = sets{dim}(i);
    end

    % Move on to the next set.
    product = setCrossProduct(sets, dim+1, new_product);
  end


text:
from raw._ebuttdt import *
from raw import _ebuttdt as ebuttdt_raw
from datetime import timedelta
from decimal import Decimal
import re, logging
import six
from pyxb.exceptions_ import SimpleTypeValueError, SimpleFacetValueError
from ebu_tt_live.errors import TimeFormatOverflowError, ExtentMissingError
from ebu_tt_live.strings import ERR_TIME_FORMAT_OVERFLOW, ERR_SEMANTIC_VALIDATION_TIMING_TYPE, ERR_1DIM_ONLY, \
    ERR_2DIM_ONLY
from .pyxb_utils import get_xml_parsing_context
from .validation.base import SemanticValidationMixin
from .validation.presentation import SizingValidationMixin

log = logging.getLogger(__name__)

def _get_time_members(checked_time):
    hours, seconds = divmod(checked_time.seconds, 3600)
    hours += checked_time.days * 24
    minutes, seconds = divmod(seconds, 60)
    milliseconds, _ = divmod(checked_time.microseconds, 1000)
    return hours, minutes, seconds, milliseconds

class _TimedeltaBindingMixin(object):
    """
    Wiring in timedelta assignment and conversion operators
    """

    # For each timing attribute a list of timeBases is specified, which represents the valid timeBase, timing attribute
    # and timing type semantic constraint.
    _compatible_timebases = {
        'begin': [],
        'dur': [],
        'end': []
    }

    @classmethod
    def compatible_timebases(cls):
        return cls._compatible_timebases

    @classmethod
    def _ConvertArguments_vx(cls, args, kw):
        """
        This hook is called before the type in question is instantiated. This is meant to do some normalization
        of input parameters and convert them to tuple. In this function we check the timeBase and the attribute name
        against our compatible_timebases mapping inside the timing type class. If an invalid scenario is encountered
        SimpleTypeValueError is raised, which effectively prevents the timingType union to instantiate the type.

        :raises pyxb.SimpleTypeValueError:
        :param args:
        :param kw:
        :return: tuple of converted input parameters.
        """
        result = []
        # In parsing mode check timebase compatibility at instantiation time. This prevents pyxb instantiating
        # the wrong type given 2 types having overlapping values in a union as it happens in full and limited
        # clock timing types.
        context = get_xml_parsing_context()
        if context is not None:
            # This means we are in XML parsing context. There should be a timeBase and a timing_attribute_name in the
            # context object.
            time_base = context['timeBase']
            # It is possible for a timing type to exist as the value of an element not an attribute,
            # in which case no timing_attribute_name is in the context; in that case don't attempt
            # to validate the data against a timebase. At the moment this only affects the
            # documentStartOfProgramme metadata element.
            if 'timing_attribute_name' in context:
                timing_att_name = context['timing_attribute_name']
                if time_base not in cls._compatible_timebases[timing_att_name]:
                    log.debug(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
                        attr_name=timing_att_name,
                        attr_type=cls,
                        attr_value=args,
                        time_base=time_base
                    ))
                    raise pyxb.SimpleTypeValueError(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
                        attr_name=timing_att_name,
                        attr_type=cls,
                        attr_value=args,
                        time_base=time_base
                    ))
        for item in args:
            if isinstance(item, timedelta):
                result.append(cls.from_timedelta(item))
            else:
                result.append(item)
        return tuple(result)

    @property
    def timedelta(self):
        return self.as_timedelta(self)

def cells_to_pixels(cells_in, root_extent, cell_resolution):
    if not isinstance(root_extent, PixelExtentType):
        raise Exception()
    if cells_in.horizontal is not None:
        # 2dimensional
        return cells_in.horizontal * root_extent.horizontal / cell_resolution.horizontal, \
               cells_in.vertical * root_extent.vertical / cell_resolution.vertical
    else:
        return cells_in.vertical * root_extent.vertical / cell_resolution.vertical,

def pixels_to_cells(pixels_in, root_extent, cell_resolution):
    if not isinstance(root_extent, PixelExtentType):
        raise Exception()
    if pixels_in.horizontal is not None:
        return pixels_in.horizontal * cell_resolution.horizontal / root_extent.horizontal, \
               pixels_in.vertical * cell_resolution.vertical / root_extent.vertical
    else:
        return pixels_in.vertical * cell_resolution.vertical / root_extent.vertical,

def named_color_to_rgba(named_color):
    color_map = {
        "transparent": "00000000",
        "black": "000000ff",
        "silver": "c0c0c0ff",
        "gray": "808080ff",
        "white": "ffffffff",
        "maroon": "800000ff",
        "red": "ff0000ff",
        "purple": "800080ff",
        "fuchsia": "ff00ffff",
        "magenta": "ff00ffff",
        "green": "008000ff",
        "lime": "00ff00ff",
        "olive": "808000ff",
        "yellow": "ffff00ff",
        "navy": "000080ff",
        "blue": "0000ffff",
        "teal": "008080ff",
        "aqua": "00ffffff",
        "cyan": "00ffffff"
    }
    return '#{}'.format(color_map[named_color])

def convert_cell_region_to_percentage(cells_in, cell_resolution):
    return '{}% {}%'.format(
        (float(cells_in.horizontal) / float(cell_resolution.horizontal)) * 100,
        (float(cells_in.vertical) / float(cell_resolution.vertical)) * 100
    )

class TwoDimSizingMixin(object):

    _groups_regex = None
    _1dim_format = None
    _2dim_format = None

    @classmethod
    def as_tuple(cls, instance):
        if cls._2dim_format is None:
            first, second = cls._groups_regex.match(instance).groups()[0], None
        else:
            first, second = cls._groups_regex.match(instance).groups()
        if second is not None:
            second = float(second)
        return float(first), second

    @classmethod
    def from_tuple(cls, instance):
        if len(instance) > 1:
            if cls._2dim_format is None:
                raise SimpleTypeValueError(cls, ERR_1DIM_ONLY.format(
                    type=cls
                ))
            return cls._2dim_format.format(*instance)
        else:
            if cls._1dim_format is None:
                raise SimpleTypeValueError(cls, ERR_2DIM_ONLY.format(
                    type=cls
                ))
            return cls._1dim_format.format(*instance)

    @property
    def horizontal(self):
        # TODO: Caching of tuple
        tup_value = self.as_tuple(self)
        if tup_value[1] is not None:
            return tup_value[0]
        else:
            return None

    @property
    def vertical(self):
        tup_value = self.as_tuple(self)
        if tup_value[1] is not None:
            return tup_value[1]
        else:
            return tup_value[0]

    @classmethod
    def _ConvertArguments_vx(cls, args, kw):
        result = []
        current_pair = []
        for item in args:
            if isinstance(item, int) or isinstance(item, float):
                current_pair.append(item)
                if len(current_pair) > 1:
                    result.append(cls.from_tuple(tuple(current_pair)))
                    current_pair = []
            else:
                result.append(item)
        if len(current_pair) > 0:
            result.append(cls.from_tuple(tuple(current_pair)))
        return tuple(result)

    def __eq__(self, other):
        if type(self) == type(other) and self.horizontal == other.horizontal and self.vertical == other.vertical:
            return True
        elif isinstance(other, six.text_type):
            return str(self) == str(other)
        else:
            return NotImplemented

class TimecountTimingType(_TimedeltaBindingMixin, ebuttdt_raw.timecountTimingType):
    """
    Extending the string type with conversions to and from timedelta
    """

    # NOTE: Update this regex should the spec change about this type
    _groups_regex = re.compile('(?P<numerator>[0-9]+(?:\\.[0-9]+)?)(?P<unit>h|ms|s|m)')
    # TODO: Consult and restrict this in an intuitive way to avoid awkward timing type combinations on the timing attributes.
    _compatible_timebases = {
        'begin': ['clock', 'media'],
        'dur': ['clock', 'media'],
        'end': ['clock', 'media']
    }

    @classmethod
    def as_timedelta(cls, instance):
        """
        Group expression with regex than switch on unit to create timedelta.
        :param instance:
        :return:
        """
        numerator, unit = cls._groups_regex.match(instance).groups()
        numerator = float(numerator)
        if unit == 's':
            return timedelta(seconds=numerator)
        elif unit == 'm':
            return timedelta(minutes=numerator)
        elif unit == 'h':
            return timedelta(hours=numerator)
        elif unit == 'ms':
            return timedelta(milliseconds=numerator)
        else:
            raise SimpleTypeValueError()

    @classmethod
    def from_timedelta(cls, instance):
        """
        Convert to one dimensional value.
        Find the smallest unit and create value using that.
        Consistency is ensured to the millisecond. Below that the number will be trimmed.
        :param instance:
        :return:
        """
        # Get the edge case out of the way even though validation will catch a 0 duration later
        if not instance:
            return '0s'
        hours, minutes, seconds, milliseconds = _get_time_members(instance)
        multiplier = 1
        numerator = 0
        unit = None
        if milliseconds:
            unit = 'ms'
            numerator += milliseconds
            multiplier *= 1000  # For the next level values so that the algo does not need to look back
        if unit or seconds:
            if not unit:
                unit = 's'
            numerator += seconds * multiplier
            multiplier *= 60
        if unit or minutes:
            if not unit:
                unit = 'm'
            numerator += minutes * multiplier
            multiplier *= 60
        if unit or hours:
            if not unit:
                unit = 'h'
            numerator += hours * multiplier
        return '{}{}'.format(numerator, unit)

ebuttdt_raw.timecountTimingType._SetSupersedingClass(TimecountTimingType)

class FullClockTimingType(SemanticValidationMixin, _TimedeltaBindingMixin, ebuttdt_raw.fullClockTimingType):
    """
    Extending the string type with conversions to and from timedelta
    """

    _compatible_timebases = {
        'begin': ['media'],
        'dur': ['media'],
        'end': ['media']
    }
    _groups_regex = re.compile('([0-9][0-9]+):([0-5][0-9]):([0-5][0-9]|60)(?:\.([0-9]+))?')

    @classmethod
    def compatible_timebases(cls):
        return cls._compatible_timebases

    @classmethod
    def as_timedelta(cls, instance):
        """
        Using regex parse value and create timedelta
        :param instance:
        :return:
        """
        hours_str, minutes_str, seconds_str, seconds_fraction_str = [x for x in cls._groups_regex.match(instance).groups()]
        milliseconds = seconds_fraction_str and float('0.' + seconds_fraction_str) * 1000 or 0
        return timedelta(hours=int(hours_str),
            minutes=int(minutes_str),
            seconds=int(seconds_str),
            milliseconds=milliseconds)

    @classmethod
    def from_timedelta(cls, instance):
        """
        Generate full clock type from timedelta
        :param instance:
        :return:
        """
        hours, minutes, seconds, milliseconds = _get_time_members(instance)
        if milliseconds:
            return '{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}'.format(
                hours=hours,
                minutes=minutes,
                seconds=seconds,
                milliseconds=milliseconds
            )
        else:
            return '{hours:02d}:{minutes:02d}:{seconds:02d}'.format(
                hours=hours,
                minutes=minutes,
                seconds=seconds
            )

ebuttdt_raw.fullClockTimingType._SetSupersedingClass(FullClockTimingType)

class LimitedClockTimingType(_TimedeltaBindingMixin, ebuttdt_raw.limitedClockTimingType):
    """
    Extending the string type with conversions to and from timedelta
    """

    _compatible_timebases = {
        'begin': ['clock'],
        'dur': ['clock'],
        'end': ['clock']
    }
    _groups_regex = re.compile('([0-9][0-9]):([0-5][0-9]):([0-5][0-9]|60)(?:\.([0-9]+))?')

    @classmethod
    def as_timedelta(cls, instance):
        """
        Using regex parse value and create timedelta
        :param instance:
        :return:
        """
        hours_str, minutes_str, seconds_str, seconds_fraction_str = [x for x in cls._groups_regex.match(instance).groups()]
        milliseconds = seconds_fraction_str and float('0.' + seconds_fraction_str) * 1000 or 0
        return timedelta(hours=int(hours_str),
            minutes=int(minutes_str),
            seconds=int(seconds_str),
            milliseconds=milliseconds)

    @classmethod
    def from_timedelta(cls, instance):
        """
        Generate limited clock type from timedelta
        :param instance:
        :return:
        """
        hours, minutes, seconds, milliseconds = _get_time_members(instance)
        # We have our most significant value. Time for range check
        if hours > 99:
            raise TimeFormatOverflowError(ERR_TIME_FORMAT_OVERFLOW)
        if milliseconds:
            return '{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}'.format(
                hours=hours,
                minutes=minutes,
                seconds=seconds,
                milliseconds=milliseconds
            )
        else:
            return '{hours:02d}:{minutes:02d}:{seconds:02d}'.format(
                hours=hours,
                minutes=minutes,
                seconds=seconds
            )

ebuttdt_raw.limitedClockTimingType._SetSupersedingClass(LimitedClockTimingType)

# NOTE: Some of the code below includes handling of SMPTE time base, which was removed from version 1.0 of the specification.

# Here comes the tricky one. The SMPTE requires knowledge about frames. The top level tt element knows the frameRate.
# Unfortunately the conversion methods run before the object gets created let alone inserted into a document structure.
# The conversion paradigm of storing data in the xml datatype does not work here. A deferred method is needed that
# will compute the appropriate value when the element is inserted into the document structure.
class SMPTETimingType(_TimedeltaBindingMixin, ebuttdt_raw.smpteTimingType):
    """
    Extending the string type with conversions to and from timedelta
    """
    _compatible_timebases = {
        'begin': ['smpte'],
        'dur': ['smpte'],
        'end': ['smpte']
    }

    @classmethod
    def as_timedelta(cls, instance):
        # TODO: implement SMPTE
        return timedelta()

    @classmethod
    def from_timedelta(cls, instance):
        # TODO: implement SMPTE
        return SMPTETimingType('00:00:00:00')

# TODO: SMPTE frameRate and frameRateMultiplier value from tt element.
ebuttdt_raw.smpteTimingType._SetSupersedingClass(SMPTETimingType)

class PixelOriginType(TwoDimSizingMixin, SizingValidationMixin, ebuttdt_raw.pixelOriginType):

    _groups_regex = re.compile('(?:[+-]?(?P<first>\d*\.?\d+)(?:px))\s(?:[+-]?(?P<second>\d*\.?\d+)(?:px))')
    _2dim_format = '{}px {}px'

    def _semantic_validate_sizing_context(self, dataset):
        extent = dataset['tt_element'].extent
        if extent is None:
            raise ExtentMissingError(self)

ebuttdt_raw.pixelOriginType._SetSupersedingClass(PixelOriginType)

class CellOriginType(TwoDimSizingMixin, ebuttdt_raw.cellOriginType):

    _groups_regex = re.compile(r'(?:[+-]?(?P<first>\d*\.?\d+)(?:c))\s(?:[+-]?(?P<second>\d*\.?\d+)(?:c))')
    _2dim_format = '{}c {}c'

ebuttdt_raw.cellOriginType._SetSupersedingClass(CellOriginType)

class PercentageOriginType(TwoDimSizingMixin, ebuttdt_raw.percentageOriginType):

    _groups_regex = re.compile('(?:[+-]?(?P<first>\d*\.?\d+)(?:%))\s(?:[+-]?(?P<second>\d*\.?\d+)(?:%))')
    _2dim_format = '{}% {}%'

ebuttdt_raw.percentageOriginType._SetSupersedingClass(PercentageOriginType)

class PixelExtentType(TwoDimSizingMixin, SizingValidationMixin, ebuttdt_raw.pixelExtentType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:px))\s(?:[+]?(?P<second>\d*\.?\d+)(?:px))')
    _2dim_format = '{}px {}px'

    def _semantic_validate_sizing_context(self, dataset):
        extent = dataset['tt_element'].extent
        if extent is None:
            raise ExtentMissingError(self)

ebuttdt_raw.pixelExtentType._SetSupersedingClass(PixelExtentType)

class CellExtentType(TwoDimSizingMixin, ebuttdt_raw.cellExtentType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:c))\s(?:[+]?(?P<second>\d*\.?\d+)(?:c))')
    _2dim_format = '{}c {}c'

ebuttdt_raw.cellExtentType._SetSupersedingClass(CellExtentType)

class PercentageExtentType(TwoDimSizingMixin, ebuttdt_raw.percentageExtentType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:%))\s(?:[+]?(?P<second>\d*\.?\d+)(?:%))')
    _2dim_format = '{}% {}%'

ebuttdt_raw.percentageExtentType._SetSupersedingClass(PercentageExtentType)

class PixelLengthType(SizingValidationMixin, ebuttdt_raw.pixelLengthType):

    def _semantic_validate_sizing_context(self, dataset):
        extent = dataset['tt_element'].extent
        if extent is None:
            raise ExtentMissingError(self)

ebuttdt_raw.pixelLengthType._SetSupersedingClass(PixelLengthType)

class PercentageLengthType(ebuttdt_raw.percentageLengthType):
    pass

ebuttdt_raw.percentageLengthType._SetSupersedingClass(PercentageLengthType)

class CellLengthType(ebuttdt_raw.cellLengthType):
    pass

ebuttdt_raw.cellLengthType._SetSupersedingClass(CellLengthType)

class PixelFontSizeType(TwoDimSizingMixin, SizingValidationMixin, ebuttdt_raw.pixelFontSizeType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:px))(?:\s(?:[+]?(?P<second>\d*\.?\d+)(?:px)))?')

    _1dim_format = '{}px'
    _2dim_format = '{}px {}px'

    def _semantic_validate_sizing_context(self, dataset):
        extent = dataset['tt_element'].extent
        if extent is None:
            raise ExtentMissingError(self)

ebuttdt_raw.pixelFontSizeType._SetSupersedingClass(PixelFontSizeType)

class CellFontSizeType(TwoDimSizingMixin, ebuttdt_raw.cellFontSizeType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:c))(?:\s(?:[+]?(?P<second>\d*\.?\d+)(?:c)))?')

    _1dim_format = '{}c'
    _2dim_format = '{}c {}c'

    def _do_div(self, other):
        """
        :param other: CellFontSizeType
        :return:
        """
        if isinstance(other, CellFontSizeType):
            result_list = []
            if self.horizontal is not None and other.horizontal is not None:
                result_list.append((float(self.horizontal) / float(other.horizontal)) * 100)
            elif self.horizontal is None and other.horizontal is not None:
                result_list.append((float(self.vertical) / float(other.horizontal)) * 100)
            elif self.horizontal is not None and other.horizontal is None:
                result_list.append((float(self.horizontal) / float(other.vertical)) * 100)
            result_list.append((float(self.vertical) / float(other.vertical)) * 100)
            return PercentageFontSizeType(*result_list)
        else:
            return NotImplemented

    def __div__(self, other):
        return self._do_div(other)

    def _do_eq(self, other):
        if isinstance(other, CellFontSizeType):
            if self.horizontal is None and other.horizontal is None:
                return self.vertical == other.vertical
            elif self.horizontal is None:
                return self.vertical == other.vertical and \
                       self.vertical == other.horizontal
            elif other.horizontal is None:
                return self.vertical == other.vertical and \
                       self.horizontal == other.vertical
            else:
                return self.vertical == other.vertical and \
                       self.horizontal == other.horizontal
        elif isinstance(other, six.text_type):
            return str(self) == str(other)
        else:
            return NotImplemented

    def __eq__(self, other):
        return self._do_eq(other)

ebuttdt_raw.cellFontSizeType._SetSupersedingClass(CellFontSizeType)

class PercentageFontSizeType(TwoDimSizingMixin, ebuttdt_raw.percentageFontSizeType):

    _groups_regex = re.compile('(?:[+]?(?P<first>\d*\.?\d+)(?:%))(?:\s(?:[+]?(?P<second>\d*\.?\d+)(?:%)))?')

    _1dim_format = '{}%'
    _2dim_format = '{}% {}%'

    def do_mul(self, other):
        if isinstance(other, CellFontSizeType):
            result_type = CellFontSizeType
        elif isinstance(other, PixelFontSizeType):
            result_type = PixelFontSizeType
        elif isinstance(other, PercentageFontSizeType):
            result_type = PercentageFontSizeType
        else:
            return NotImplemented

        if self.horizontal is not None:
            if other.horizontal is not None:
                return result_type(
                    other.horizontal * self.horizontal / 100,
                    other.vertical * self.vertical / 100
                )
            else:
                # This uses TTML's assumption of 1c => 1c 1c
                return result_type(
                    other.vertical * self.horizontal / 100,
                    other.vertical * self.vertical / 100
                )
        else:
            if other.horizontal is not None:
                return result_type(
                    other.horizontal * self.vertical / 100,
                    other.vertical * self.vertical / 100
                )
            else:
                return result_type(
                    other.vertical * self.vertical / 100
                )

    def __mul__(self, other):
        return self.do_mul(other)

    def __rmul__(self, other):
        return self.do_mul(other)

ebuttdt_raw.percentageFontSizeType._SetSupersedingClass(PercentageFontSizeType)

class CellResolutionType(TwoDimSizingMixin, ebuttdt_raw.cellResolutionType):

    _groups_regex = re.compile('(?P<first>[0]*[1-9][0-9]*)\s(?P<second>[0]*[1-9][0-9]*)')
    _2dim_format = '{} {}'

ebuttdt_raw.cellResolutionType._SetSupersedingClass(CellResolutionType)

class CellLineHeightType(TwoDimSizingMixin, ebuttdt_raw.cellLineHeightType):

    _groups_regex = re.compile('(?P<first>\d*\.?\d+)c')
    _1dim_format = '{}c'

ebuttdt_raw.cellLineHeightType._SetSupersedingClass(CellLineHeightType)

class PercentageLineHeightType(TwoDimSizingMixin, ebuttdt_raw.percentageLineHeightType):

    _groups_regex = re.compile('(?P<first>\d*\.?\d+)%')
    _1dim_format = '{}%'

    def do_mul(self, other):
        if isinstance(other, CellFontSizeType):
            return CellLineHeightType(self.vertical * other.vertical / 100)
        else:
            return NotImplemented

    def __mul__(self, other):
        return self.do_mul(other)

    def __rmul__(self, other):
        return self.do_mul(other)

ebuttdt_raw.percentageLineHeightType._SetSupersedingClass(PercentageLineHeightType)

class PixelLineHeightType(TwoDimSizingMixin, ebuttdt_raw.pixelLineHeightType):

    _groups_regex = re.compile('(?P<first>\d*\.?\d+)px')
    _1dim_format = '{}px'

ebuttdt_raw.pixelLineHeightType._SetSupersedingClass(PixelLineHeightType)


text:
- Fixed an error that caused the plugin to crash when converting decimal to hexadecimal. (issue #1).
- Added unit tests and continuous integration.

## Version 1.0.1

- Update README

## Version 1.0.0

- Convert Hex to Decimal
- Convert Decimal to Hex


text:
$.ajax({
    type: "POST",
    url: "https://cp.pushwoosh.com/json/1.3/createMessage",
    data: JSON.stringify({
        "request": {
            "application": "APPLICATION CODE",
            "auth": "API TOKEN",
            "notifications": [{
                "send_date": "now",
                "ignore_user_timezone": true,
                "content": "Hello world!"
            }]
        }
    }),
    dataType: "json"
}).done(function(data) {
    console.log(data);
});


text:
> Easily add plugin support to your node.js application.

## Install

Install with [npm](https://www.npmjs.com/):

```sh
$ npm install --save use
```

A different take on plugin handling! This is not a middleware system, if you need something that handles async middleware, [ware](https://github.com/segmentio/ware) is great for that.

## Usage

```js
var use = require('use');
```

See the [examples folder](./examples) for usage examples.

## About

### Related projects

* [base-plugins](https://www.npmjs.com/package/base-plugins): Upgrade's plugin support in base applications to allow plugins to be called any time after… [more](https://github.com/node-base/base-plugins) | [homepage](https://github.com/node-base/base-plugins "Upgrade's plugin support in base applications to allow plugins to be called any time after init.")
* [base](https://www.npmjs.com/package/base): base is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting… [more](https://github.com/node-base/base) | [homepage](https://github.com/node-base/base "base is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`.")
* [ware](https://www.npmjs.com/package/ware): Easily create your own middleware layer. | [homepage](https://github.com/segmentio/ware "Easily create your own middleware layer.")

### Contributing

Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).

### Contributors

| **Commits** | **Contributor** |
| --- | --- |
| 22 | [jonschlinkert](https://github.com/jonschlinkert) |
| 7 | [tunnckoCore](https://github.com/tunnckoCore) |
| 2 | [doowb](https://github.com/doowb) |
| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |

### Building docs

_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_

To generate the readme, run the following command:

```sh
$ npm install -g verbose/verb#dev verb-generate-readme && verb
```

### Running tests

Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

```sh
$ npm install && npm test
```

### Author

**Jon Schlinkert**

* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)

### License

Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).

***

_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.2, on February 25, 2017._


text:
//
//  LJLimitTimeViewController.m
//  xianchufang
//
//  Created by zhenglong duan on 09/03/2017.
//  Copyright © 2017 zhenglong duan. All rights reserved.
//

#import "LJLimitTimeViewController.h"
#import "LJLastTimeView.h"
#import "LJLimitTimeTableViewCell.h"

@interface LJLimitTimeViewController ()
/*** banner图片 ***/
@property (nonatomic,strong) UIImageView *bannerImageView;
/*** 计时器 ***/
@property (nonatomic,strong) NSTimer *Timer;
/*** 剩余时间 ***/
@property (nonatomic,assign) NSUInteger lastTime;
/*** 剩余时间Label显示 ***/
@property (nonatomic,strong) LJLastTimeView *LastTimeView;
/*** 提示label ***/
@property (nonatomic,strong) UILabel *tipLabel;
@end

@implementation LJLimitTimeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setNavigaitonFont];  //1.设置导航栏字体
    [self setupBanner];        //2.设置Banner
    [self activityTime];       //3.活动时间
    [self setupBaseInfo];      //4.tableView基本属性
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}

#pragma mark --setNavigationFont 设置导航栏字体
- (void)setNavigaitonFont {
    UIImageView *titleViewImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
    titleViewImage.image = [UIImage imageNamed:@"home_miaosha_icon"];
    [titleViewImage sizeToFit];
    [self.navigationItem setTitleView:titleViewImage];
}

#pragma mark --banner
- (void)setupBanner {
    self.bannerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 64, SCREEN_WIDTH, spaceEdgeH(120))];
    self.bannerImageView.backgroundColor = LJRandomColor;
    self.bannerImageView.image = [UIImage imageNamed:@""];
    [self.view addSubview:self.bannerImageView];
}

#pragma mark --activity time 活动时间
- (void)activityTime {
    UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, self.bannerImageView.lj_bottom, SCREEN_WIDTH, spaceEdgeH(45))];
    bgView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:bgView];

    UILabel *tipLabel  = [[UILabel alloc] initWithFrame:CGRectMake(spaceEdgeW(10), 0, spaceEdgeW(120), spaceEdgeH(20))];
    tipLabel.lj_centerY = bgView.lj_height / 2;
    tipLabel.textColor = LJTheMeColor;
    tipLabel.font = LJFontSize18;
    tipLabel.text = @"活动持续时间";
    [bgView addSubview:tipLabel];
    self.tipLabel = tipLabel;

    self.LastTimeView = [[NSBundle mainBundle] loadNibNamed:@"LJLastTimeView" owner:nil options:nil].lastObject;
    self.LastTimeView.frame = CGRectMake(SCREEN_WIDTH - 140, 0, 120, spaceEdgeH(45));
    [bgView addSubview:self.LastTimeView];
    //从后台获取活动还剩的时间  、、这里模拟数据
    self.lastTime = 10;
    [self startTimer];
}

#pragma mark --tableView 基本属性
- (void)setupBaseInfo {
    self.tableView.lj_y = 64 + spaceEdgeH(170);
    self.tableView.lj_height = SCREEN_HEIGHT - 64 - spaceEdgeH(170);
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    [self.view addSubview:self.tableView];
    [self.tableView registerClass:[LJLimitTimeTableViewCell class] forCellReuseIdentifier:@"LJLimitTimeTableViewCell"];
}

#pragma mark --tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    LJLimitTimeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"LJLimitTimeTableViewCell"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return spaceEdgeH(110);
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UIViewController *vc = [NSClassFromString(@"LJGoodsDetailFatherViewController") new];
    [self.navigationController pushViewController:vc animated:YES];
}

//倒计时
- (void)startTimer
{
    self.Timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshLessTime) userInfo:@"" repeats:YES];
}

- (void)refreshLessTime {
    NSUInteger time;
    if (self.lastTime == 0) {
        time = 0;
    }else{
        time = self.lastTime --;
    }
    NSString *timeStr = [self lessSecondToDay:time];
    if ([timeStr isEqualToString:@"已结束"]) {timeStr = @"00:00:00";self.tipLabel.text = @"活动已结束!";}
    self.LastTimeView.Hour1Label.text = [timeStr substringWithRange:NSMakeRange(0, 1)];
    self.LastTimeView.Hour2Label.text = [timeStr substringWithRange:NSMakeRange(1, 1)];
    self.LastTimeView.Min1Label.text = [timeStr substringWithRange:NSMakeRange(3, 1)];
    self.LastTimeView.Min2Label.text = [timeStr substringWithRange:NSMakeRange(4, 1)];
    self.LastTimeView.Second1Label.text = [timeStr substringWithRange:NSMakeRange(6, 1)];
    self.LastTimeView.Second2Label.text = [timeStr substringWithRange:NSMakeRange(7, 1)];
}

//根据秒数计算剩余时间:天,小时,分钟,秒
- (NSString *)lessSecondToDay:(NSUInteger)seconds
{
    NSUInteger hour = (NSUInteger)(seconds%(24*3600))/3600;
    NSUInteger min  = (NSUInteger)(seconds%(3600))/60;
    NSUInteger second = (NSUInteger)(seconds%60);
    NSString *timeStr;
    if (seconds == 0) {
        timeStr = @"已结束";
        [self removeTimer];
    }else{
        timeStr = [NSString stringWithFormat:@"%02zd:%02zd:%02zd",(unsigned long)hour,(unsigned long)min,(unsigned long)second];
    }
    return timeStr;
}

//移除计时器
- (void)removeTimer {
    [self.Timer invalidate];
    self.Timer = nil;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    NSArray *viewControllers = self.navigationController.viewControllers;
    if ([viewControllers indexOfObject:self] == NSNotFound) {
        [self removeTimer]; //当是pop时就消毁计时器
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end


text:
ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true

class Dashboard
  include ActionView::Helpers
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name, :type => String
  field :slug, :type => String
  field :custom_url, :type => String
  field :shared_with_emails, :type => Array, :default => []
  field :is_public, :type => Boolean, :default => false
  field :css, :type => String
  field :custom_html, :type => String, :default => nil
  field :style
  field :is_facebook_stream, :type => Boolean
  field :user_id, :type => Integer
  field :interests, :type => Hash
  field :disinterests, :type => Hash
  field :is_recommended, :type => Boolean
  field :opml_to_import, :type => String

  validates_uniqueness_of :name, :scope => [:user_id]
  validates_presence_of :name

  validates_uniqueness_of :slug, :allow_blank => true
  validates_uniqueness_of :custom_url, :allow_blank => true

  has_and_belongs_to_many :sources, :validate => false, :index => true

  has_and_belongs_to_many :feeds, :validate => false, :index => true

  has_many :posts, :dependent => :destroy, :validate => false

  embeds_many :statistics
  accepts_nested_attributes_for :statistics

  has_many :url_references, :validate => false

  accepts_nested_attributes_for :url_references

  scope :shared_with, lambda {|user|
    if user.admin?
      where(:id => :id)
    else
      # self.or({:shared_with_emails => [user.email]}, {:is_public => true})
      where(:shared_with_emails => [user.email])
    end
  }

  def user
    User.find_by_id(user_id)
  end

  def shared_with?(user)
    shared_with_emails.include?(user.email)
  end

  before_save :set_shared_with
  before_save :set_slug
  after_save :set_custom_domain

  after_create :queue_worker
  after_create :schedule_processed_notification_worker

  attr_accessor :shared_with_emails_string
  attr_accessor :inputs

  def queue_worker
    if is_recommended?
      RecommendedDashboardWorker.perform_async(self.id.to_s, 3.days.ago)
    else
      DashboardWorker.perform_async(self.to_param)
    end
  end

  def set_slug
    if custom_url
      self.slug = custom_url
    end
  end

  def set_custom_domain
    # if Rails.env.staging? || Rails.env.production?
    #   if !new_record? && custom_url_changed? && !custom_url.blank?
    #     heroku_client = Heroku::Client.new(ENV['HEROKU_USERNAME'], ENV['HEROKU_PASSWORD'])
    #     heroku_client.remove_domain(ENV['HEROKU_APP'], custom_url_was) unless custom_url_was.blank?
    #     heroku_client.add_domain(ENV['HEROKU_APP'], custom_url) unless !custom_url.blank?
    #   end
    # end
  end

  def set_shared_with
    shared_with_emails_string.split(',').each do |email|
      if u = User.where(:email => email).first
        shared_with_emails << u.email
      end
    end unless shared_with_emails_string.blank?
    shared_with_emails.uniq!
  end

  def add_inputs(screen_names_or_feed_uris)
    successes, errors = [], []

    if screen_names_or_feed_uris.is_a?(String)
      screen_names_or_feed_uris = screen_names_or_feed_uris.split("\n")
    end

    screen_names_or_feed_uris.each do |string|
      next if string.blank?

      if google_news_search = Feed.google_news_search?(string.strip)
        if s = Feed.add_google_news(google_news_search)
          self.feeds << s
          successes << s
        else
          errors << s
        end
      elsif screenname = Source.screenname?(string.strip)
        if s = Source.find_or_create_by(:name => screenname)
          self.sources << s
          successes << s
        else
          errors << s
        end
      elsif uri = Feed.feed?(string.strip)
        if s = Feed.find_or_create_by(:uri => uri)
          self.feeds << s
          successes << s
        else
          errors << s
        end
      end
    end
    return [successes, errors]
  end

  def add_fb_friends(array)
    array.each do |hash|
      self.sources.create(:name => hash['name'], :fb_uid => hash['id'])
    end
  end

  def urls(page = 1, per = 30)
    references = url_references.only(:url_id).where(:classification.ne => :bad)

    if page
      references = references.limit(100).offset((page.to_i-1)*per.to_i)
    end

    references = references.to_a.map(&:url_id).compact

    us = Url.in(:id => references)
  end

  def urls=(array)
    self.url_references.destroy_all
    add_urls(array)
    self.touch
  end

  def add_urls(array)
    array.each do |u|
      add_url(u)
    end
    self.touch
  end

  def add_urls_async(array)
    array.each do |u|
      add_url_async(u)
    end
  end

  def add_url_async(url)
    DashboardUrlWorker.perform_async(self.id.to_s, url.id.to_s)
  end

  def add_url(url)
    url.reload
    return unless self.should_add_url?(url)

    ref = UrlReference.find_or_initialize_by(:url_id => url.id, :dashboard_id => self.id)
    ref.source_ids = url.cached_sources
    ref.feed_ids   = url.cached_feeds
    ref.with(safe: true).save
    self.touch
  end

  def should_add_url?(url)
    #filter - which URLs should belong?
    (url.score >= 0) &&
      (!url.title.blank?) &&
      (url.image_count > 0 || url.video_count > 0 || !url.body.blank?)
  end

  def refresh_url_references
    Url.any_in(:dashboard_ids => [self.id]).each do |url|
      ref = self.url_references.find_or_create_by(:url_id => url.id)
    end
  end

  def reclassify_url_references
    url_references.each do |ref|
      ref.classify
    end
  end

  def unread_count(time)
    count = urls.with_images_or_video.where(:created_at.gte => (time || 1.year.ago) ).count
    count = "Lots" if (count > 100)
    count
  end

  def process_inputs
    sources.each do |source|
      source.queue_worker
    end
    feeds.each do |feed|
      feed.queue_worker
    end
  end

  def process_urls(only_unprocessed = true, limit = 100)
    to_process = self.urls
    if only_unprocessed
      to_process = to_process.where(:last_processed_at.exists => false).limit(limit)
    end

    to_process.each do |u|
      u.queue_worker
    end
  end

  def cache_key(suffix=nil)
    "dashboard-#{self.id}-#{self.updated_at.to_i}#{suffix}"
  end

  def processing?
    Rails.cache.fetch(cache_key('processing?')) do
      url_references.empty?
    end
  end

  def cover_image
    Rails.cache.fetch(cache_key('cover-image')) do
      img = nil
      url_references.desc(:created_at).each do |ref|
        if img = ref.url.image
          break
        end
      end
      img ? img : "/assets/img-01.jpg"
    end
  end

  def self.public_dashboard_ids(current_user=nil)
    user_id = current_user && current_user.id
    Dashboard.or({:is_public => true}, {:user_id => user_id}).all.map(&:id)
  end

  def bayes_keywords
    c = UrlClassifier.new(self.id)
    words = c.database["dashboard_#{self.id.to_s}_word_frequencies"].find

    results = {'good' => [], 'bad' => []}

    words.each do |h|
      if h['good']
        results['good'] << h['word'].to_s
      end

      if h['bad']
        results['bad'] << h['word'].to_s
      end
    end

    return results
  end

  def min_score_for(type = 'source', scalar = 2)
    stats = Statistic.send("average_#{type}_score_with_deviation", self)
    min = stats[0] - (stats[1] * scalar)
  end

  def source_ids_not_in_score_deviation_with_floor(floor = 0)
    source_min = min_score_for('source')

    if source_min && source_min < floor
      source_ids = self.sources.where(:"scores.#{self.id.to_s}".lte => source_min).map(&:id)
    end

    source_ids.blank? ? nil : source_ids
  end

  def feed_ids_not_in_score_deviation_with_floor(floor = 0)
    feed_min = min_score_for('feed')

    if feed_min && feed_min < floor
      feed_ids = self.feeds.where(:"scores.#{self.id.to_s}".lte => feed_min.to_f).map(&:id).to_a
    end

    feed_ids.blank? ? nil : feed_ids
  end

  def as_json(args)
    return { :id => id,
      :style => style,
      :custom_html => custom_html,
      :css => css,
      :name => name}
  end

  def train(sentiment, url)
    UrlClassifier.train(sentiment, url, self.id)
  end

  def classify(url)
    UrlClassifier.classify(url, self.id)
  end

  def empty?
   !is_recommended? && (sources.count + feeds.count) == 0
  end

  def import_opml_from_url(url)
    file = open(url)
    contents = file.read
    opml = OpmlSaw::Parser.new(contents)
    opml.parse
    feeds = opml.feeds.map{|h| h[:xml_url] }
    self.add_inputs(feeds)
  end

  def schedule_processed_notification_worker
    User.delay_for(10.minutes, :retry => false, :queue => :critical).check_for_processed_dashboards(self.user_id, self.id)
  end

  # Rails Admin
  rails_admin do

    edit do
      include_all_fields
      exclude_fields :url_references, :posts, :statistics
    end

    list do
      field :name
      field :user_id do
        pretty_value do
          if user = bindings[:object].user
            bindings[:view].link_to user.full_name, bindings[:view].rails_admin.show_path('user', user)
          else
            bindings[:view].link_to value, bindings[:view].rails_admin.show_path('user', value)
          end
        end
      end
      field :updated_at
      field :url_references do
        pretty_value do
          value.length.to_s
        end
      end
    end

    show do
      field :name
      field :user_id do
        pretty_value do
          if user = bindings[:object].user
            bindings[:view].link_to user.full_name, bindings[:view].rails_admin.show_path('user', user)
          else
            bindings[:view].link_to value, bindings[:view].rails_admin.show_path('user', value)
          end
        end
      end
      field :is_public
      field :is_recommended
      field :updated_at
      field :url_references do
        pretty_value do
          value.length.to_s
        end
      end

    end

  end

end