text:
#include "aggregate_sort.hpp"

#include <algorithm>
#include <memory>
#include <vector>

#include "aggregate/aggregate_traits.hpp"
#include "all_type_variant.hpp"
#include "constant_mappings.hpp"
#include "expression/pqp_column_expression.hpp"
#include "operators/sort.hpp"
#include "storage/pos_lists/entire_chunk_pos_list.hpp"
#include "storage/segment_iterate.hpp"
#include "table_wrapper.hpp"
#include "types.hpp"

namespace {

using namespace hyrise;  // NOLINT

std::shared_ptr<const Table> sort_table_by_column_ids(const std::shared_ptr<const Table>& table_to_sort,
                                                      const std::vector<ColumnID>& column_ids) {
  // Create sort definition vector from group by list for sort operator
  auto sort_definitions = std::vector<SortColumnDefinition>{};
  sort_definitions.reserve(column_ids.size());
  for (const auto& column_id : column_ids) {
    sort_definitions.emplace_back(SortColumnDefinition{column_id, SortMode::Ascending});
  }

  const auto table_wrapper = std::make_shared<TableWrapper>(table_to_sort);
  table_wrapper->execute();

  const auto sort = std::make_shared<Sort>(table_wrapper, sort_definitions);
  sort->execute();

  return sort->get_output();
}

}  // namespace

namespace hyrise {

AggregateSort::AggregateSort(const std::shared_ptr<AbstractOperator>& input_operator,
                             const std::vector<std::shared_ptr<AggregateExpression>>& aggregates,
                             const std::vector<ColumnID>& groupby_column_ids)
    : AbstractAggregateOperator(input_operator, aggregates, groupby_column_ids) {}

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

/**
 * Calculates the value for the aggregate_index'th aggregate.
 * To do this, we iterate over all segments of the corresponding column.
 * The aggregate values (one per group-by-combination) are built incrementally.
 * Every time we reach the beginning of a new group-by-combination,
 * we store the aggregate value for the current (now previous) group.
 *
 * @tparam ColumnType the type of the input column to aggregate on
 * @tparam AggregateType the type of the aggregate (=output column)
 * @tparam aggregate_function as type parameter - e.g. AggregateFunction::MIN, AVG, COUNT, ...
 * @param group_boundaries the row ids where a new combination in the sorted table begins
 * @param aggregate_index determines which aggregate to calculate (from _aggregates)
 * @param aggregate_function the aggregate function - as callable object. This should always be the same as aggregate_function
 * @param sorted_table the input table, sorted by the group by columns
 */
template <typename ColumnType, typename AggregateType, AggregateFunction aggregate_function>
void AggregateSort::_aggregate_values(const std::set<RowID>& group_boundaries, const uint64_t aggregate_index,
                                      const std::shared_ptr<const Table>& sorted_table) {
  const auto& pqp_column = static_cast<const PQPColumnExpression&>(*_aggregates[aggregate_index]->argument());
  const auto input_column_id = pqp_column.column_id;

  auto aggregator = AggregateFunctionBuilder<ColumnType, AggregateType, aggregate_function>().get_aggregate_function();

  // We already know beforehand how many aggregate values (=group-by-combinations) we have to calculate
  const auto num_groups = group_boundaries.size() + 1;

  // Vectors to store aggregate values (and if they are NULL) for later usage in value segments
  auto aggregate_results = pmr_vector<AggregateType>(num_groups);
  auto aggregate_null_values = pmr_vector<bool>(num_groups);

  // Variables needed for the aggregates. Not all variables are needed for all aggregates

  // Row counts per group, ex- and including null values. Needed for count (<column>/*) and average
  auto value_count = uint64_t{0};
  auto value_count_with_null = uint64_t{0};

  // All unique values found. Needed for count distinct
  auto unique_values = std::unordered_set<ColumnType>{};

  // The number of the current group-by-combination. Used as offset when storing values
  auto aggregate_group_index = uint64_t{0};

  const auto chunk_count = sorted_table->chunk_count();

  AggregateAccumulator<aggregate_function, AggregateType> accumulator{};
  auto current_chunk_id = ChunkID{0};
  if (aggregate_function == AggregateFunction::Count && input_column_id == INVALID_COLUMN_ID) {
    /*
     * Special COUNT(*) implementation.
     * We do not need to care about null values for COUNT(*).
     * Because of this, we can simply calculate the number of elements per group (=COUNT(*))
     * by calculating the distance between the first and the last corresponding row (+1) in the table.
     * This results in a runtime of O(output rows) rather than O(input rows), which can be quite significant.
     */
    auto current_group_begin_pointer = RowID{ChunkID{0u}, ChunkOffset{0}};
    for (const auto& group_boundary : group_boundaries) {
      if (current_group_begin_pointer.chunk_id == group_boundary.chunk_id) {
        // Group is located within a single chunk
        value_count_with_null = group_boundary.chunk_offset - current_group_begin_pointer.chunk_offset;
      } else {
        // Group is spread over multiple chunks
        auto count = uint64_t{0};
        count += sorted_table->get_chunk(current_group_begin_pointer.chunk_id)->size() -
                 current_group_begin_pointer.chunk_offset;
        for (auto chunk_id = ChunkID{current_group_begin_pointer.chunk_id + 1}; chunk_id < group_boundary.chunk_id;
             chunk_id++) {
          count += sorted_table->get_chunk(chunk_id)->size();
        }
        count += group_boundary.chunk_offset + 1;
        value_count_with_null = count;
      }
      _set_and_write_aggregate_value<AggregateType, aggregate_function>(
          aggregate_results, aggregate_null_values, aggregate_group_index, aggregate_index, accumulator, value_count,
          value_count_with_null, unique_values.size());
      current_group_begin_pointer = group_boundary;
      aggregate_group_index++;
    }
    // Compute value count with null values for the last iteration
    value_count_with_null = sorted_table->get_chunk(current_group_begin_pointer.chunk_id)->size() -
                            current_group_begin_pointer.chunk_offset;
    for (auto chunk_id = ChunkID{current_group_begin_pointer.chunk_id + 1}; chunk_id < chunk_count; chunk_id++) {
      value_count_with_null += sorted_table->get_chunk(chunk_id)->size();
    }

  } else {
    /*
     * High-level overview of the algorithm:
     *
     * We already know at which RowIDs a new group (=group-by-combination) begins,
     * it is stored in group_boundaries.
     * The base idea is:
     *
     * Iterate over every value in the aggregate column, and keep track of the current RowID
     *   if (current row id == start of next group)
     *     write aggregate value of the just finished group
     *     reset helper variables
     *
     *   update helper variables
     *
     */
    auto group_boundary_iter = group_boundaries.cbegin();
    for (auto chunk_id = ChunkID{0}; chunk_id < chunk_count; ++chunk_id) {
      auto segment = sorted_table->get_chunk(chunk_id)->get_segment(input_column_id);
      segment_iterate<ColumnType>(*segment, [&](const auto& position) {
        const auto row_id = RowID{current_chunk_id, position.chunk_offset()};
        const auto is_new_group = group_boundary_iter != group_boundaries.cend() && row_id == *group_boundary_iter;
        const auto& new_value = position.value();
        if (is_new_group) {
          // New group is starting. Store the aggregate value of the just finished group
          _set_and_write_aggregate_value<AggregateType, aggregate_function>(
              aggregate_results, aggregate_null_values, aggregate_group_index, aggregate_index, accumulator,
              value_count, value_count_with_null, unique_values.size());

          // Reset helper variables
          accumulator = {};
          unique_values.clear();
          value_count = 0u;
          value_count_with_null = 0u;

          // Update indexing variables
          aggregate_group_index++;
          group_boundary_iter++;
        }

        // Update helper variables
        if (!position.is_null()) {
          aggregator(new_value, value_count, accumulator);
          value_count++;
          if constexpr (aggregate_function == AggregateFunction::CountDistinct) {
            unique_values.insert(new_value);
          } else if constexpr (aggregate_function == AggregateFunction::Any) {
            // Gathering the group's first value for ANY() is sufficient
            return;
          }
        }
        value_count_with_null++;
      });
      current_chunk_id++;
    }
  }
  // Aggregate value for the last group was not written yet
  _set_and_write_aggregate_value<AggregateType, aggregate_function>(
      aggregate_results, aggregate_null_values, aggregate_group_index, aggregate_index, accumulator, value_count,
      value_count_with_null, unique_values.size());

  // Store the aggregate values in a value segment
  if (_output_column_definitions.at(aggregate_index + _groupby_column_ids.size()).nullable) {
    _output_segments[aggregate_index + _groupby_column_ids.size()] =
        std::make_shared<ValueSegment<AggregateType>>(std::move(aggregate_results), std::move(aggregate_null_values));
  } else {
    _output_segments[aggregate_index + _groupby_column_ids.size()] =
        std::make_shared<ValueSegment<AggregateType>>(std::move(aggregate_results));
  }
}

/**
 * This is a generic method to add an aggregate value to the current aggregate value vector (`aggregate_results`).
 * While adding the new value itself is easy, deciding on what exactly the new value is might be not that easy.
 *
 * Sometimes it is simple, e.g. for Min, Max and Sum the value we want to add is directly the `accumulator`.
 * But sometimes it is more complicated, e.g. Avg effectively only calculates a sum, and we manually need to divide the
 * sum by the number of (non-null) elements that contributed to it. Further, Count and CountDistinct do not use
 * `current_x_aggregate`, instead we pass `value_count` and `value_count_with_null` directly to the function. The latter
 * might look ugly at the first sight, but we need those counts (or at least `value_count`) anyway for Avg, and it is
 * consistent with the hash aggregate.
 *
 * The function is "generic" in the sense that it works for every aggregate type.
 * This way, we can have a single call that is valid for all aggregate functions, which increases readability.
 * We pay for this easy call with more function parameters than we might need.
 * As a result, we have to mark most of the parameters with [[maybe_unused]] to avoid compiler complaints.
 * Note: if a parameter is not used for a certain aggregate type, it might not contain meaningful values.
 *
 *
 * @tparam AggregateType the data type of the aggregate result
 * @tparam aggregate_function as type parameter - e.g. AggregateFunction::Min, Max, ...
 * @param aggregate_results the vector where the aggregate values should be stored
 * @param aggregate_null_values the vector indicating whether a specific aggregate value is null
 * @param aggregate_group_index the offset to use for `aggregate_results` and `aggregate_null_values`
 * @param aggregate_index current aggregate's offset in `_aggregates`
 * @param accumulator the value of the aggregate (return value of the aggregate function) - used by all except
 *                    COUNT(<expr>) and COUNT(*)
 * @param value_count the number of non-null values - used by COUNT(<expr>), AVG
 * @param value_count_with_null the number of rows  - used by COUNT(*)
 * @param unique_value_count the number of unique values
 */
template <typename AggregateType, AggregateFunction aggregate_function>
void AggregateSort::_set_and_write_aggregate_value(
    pmr_vector<AggregateType>& aggregate_results, pmr_vector<bool>& aggregate_null_values,
    const uint64_t aggregate_group_index, [[maybe_unused]] const uint64_t aggregate_index,
    AggregateAccumulator<aggregate_function, AggregateType>& accumulator, [[maybe_unused]] const uint64_t value_count,
    [[maybe_unused]] const uint64_t value_count_with_null, [[maybe_unused]] const uint64_t unique_value_count) const {
  auto is_null = value_count == 0;

  if constexpr (aggregate_function == AggregateFunction::Count) {
    const auto& pqp_column = static_cast<const PQPColumnExpression&>(*this->_aggregates[aggregate_index]->argument());
    const auto input_column_id = pqp_column.column_id;

    if (input_column_id != INVALID_COLUMN_ID) {
      // COUNT(<expr>), so exclude null values
      accumulator = value_count;
    } else {
      // COUNT(*), so include null values
      accumulator = value_count_with_null;
    }

    // COUNT is never NULL
    is_null = false;
  }

  if constexpr (aggregate_function == AggregateFunction::Avg && std::is_arithmetic_v<AggregateType>) {
    if (value_count > 0) {
      accumulator = accumulator / static_cast<AggregateType>(value_count);
    }
  }

  if constexpr (aggregate_function == AggregateFunction::CountDistinct) {
    accumulator = unique_value_count;

    // COUNT is never NULL
    is_null = false;
  }

  if constexpr (aggregate_function == AggregateFunction::StandardDeviationSample) {
    if (!std::is_same_v<AggregateType, pmr_string>) {
      if (value_count >= 2) {
        aggregate_results[aggregate_group_index] = accumulator[3];
      } else {
        // STDDEV_SAMP is undefined for lists with less than two elements
        is_null = true;
      }
    } else {
      Fail("StandardDeviationSample does not work for strings");
    }
  } else {
    aggregate_results[aggregate_group_index] = accumulator;
  }

  aggregate_null_values[aggregate_group_index] = is_null;
}

Segments AggregateSort::_get_segments_of_chunk(const std::shared_ptr<const Table>& input_table,
                                               const ChunkID chunk_id) {
  Segments segments{};
  const auto column_count = input_table->column_count();
  segments.reserve(column_count);
  const auto chunk = input_table->get_chunk(chunk_id);

  for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
    segments.emplace_back(chunk->get_segment(column_id));
  }
  return segments;
}

std::shared_ptr<Table> AggregateSort::_sort_table_chunk_wise(const std::shared_ptr<const Table>& input_table,
                                                             const std::vector<ColumnID>& groupby_column_ids) {
  auto output_table = std::make_shared<Table>(input_table->column_definitions(), TableType::References);

  const auto chunk_count = input_table->chunk_count();
  const auto column_count = input_table->column_count();
  for (auto chunk_id = ChunkID{0}; chunk_id < chunk_count; ++chunk_id) {
    const auto chunk = input_table->get_chunk(chunk_id);
    Assert(chunk, "Physically deleted chunk should not reach this point, see get_chunk / #1686.");

    const auto& chunk_sorted_by = input_table->get_chunk(chunk_id)->individually_sorted_by();

    // We can skip sorting the chunk only if we group by a single column and the chunk is sorted by that column. We do
    // not store information about cascadingly sorted chunks, which we would need for skipping the sort step with
    // multiple group by columns. The sort mode can be neglected as the aggregate only requires consecutiveness of
    // values.
    const auto single_column_group_by = groupby_column_ids.size() == 1;
    const auto chunk_sorted_by_first_group_by_column =
        std::find_if(chunk_sorted_by.cbegin(), chunk_sorted_by.cend(), [&](const auto& sort_definition) {
          return groupby_column_ids[0] == sort_definition.column;
        }) != chunk_sorted_by.cend();

    if (single_column_group_by && chunk_sorted_by_first_group_by_column) {
      if (input_table->type() == TableType::Data) {
        // Since the chunks that actually have to be sorted will be returned as referencing chunks, we need to forward
        // the already sorted input chunks as such too, using an EntireChunkPosList.
        const auto pos_list = std::make_shared<EntireChunkPosList>(chunk_id, chunk->size());
        auto reference_segments = Segments{};
        reference_segments.reserve(column_count);

        // Create actual ReferenceSegment objects.
        for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
          auto ref_segment_out = std::make_shared<ReferenceSegment>(input_table, column_id, pos_list);
          reference_segments.push_back(ref_segment_out);
        }

        output_table->append_chunk(reference_segments);
      } else {
        // In case of a reference segment, we can directly forward it.
        output_table->append_chunk(_get_segments_of_chunk(input_table, chunk_id));
      }
    } else {
      // Creating a new table holding only the current chunk and pass it to the sort operator.
      auto single_chunk_table = std::make_shared<Table>(input_table->column_definitions(), input_table->type());
      Segments segments;
      segments.reserve(column_count);
      for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
        segments.emplace_back(chunk->get_segment(column_id));
      }
      single_chunk_table->append_chunk(segments);
      const auto sorted_single_chunk_table = sort_table_by_column_ids(single_chunk_table, groupby_column_ids);

      output_table->append_chunk(_get_segments_of_chunk(sorted_single_chunk_table, ChunkID{0}));
    }
  }

  return output_table;
}

/**
 * Executes the sort-based aggregation.
 *
 * High-level overview:
 * 1. Make sure the aggregates are valid.
 * 2. Build the output table definition.
 *    - If empty, return (empty) result table.
 * 3. Sort the input table by group by columns using the sort operator.
 *    - depending on characteristics of the input table, sorting can either be skipped (input already sorted by group
 *      by column) or sorting can be limited to chunks instead of sorting the whole table (input table is clustered)
 * 4. Find the group boundaries.
 *    - The unit of aggregation (either chunks or the whole table, depending on the table's value clustering) is now
 *      sorted by all group by columns.
 *    - As a result, all rows that fall into the same group are consecutive within that unit.
 *    - Thus, we can find all group boundaries (specifically their first element) by iterating over the group by
 *      columns and storing RowIDs of rows where the value of any group by column changes.
 *    - The result is a (sorted) vector of RowIDs, its entries marking the beginning of a new group-by-combination.
 * 5. Write the values of group by columns for each group into a ValueSegment.
 *    - For each group by column, iterate over the group boundaries (RowIDs) and output the value.
 *    - Note: This cannot be merged with the first iteration (finding group boundaries). This is because we have to
 *            output values for all RowIDs where ANY group by column changes, not only the one we currently iterate
 *            over.
 * 6. Call _aggregate_values for each aggregate, which performs the aggregation and writes the output into
 *    ValueSegments.
 */
std::shared_ptr<const Table> AggregateSort::_on_execute() {
  const auto input_table = left_input_table();

  // Check for invalid aggregates
  _validate_aggregates();

  // Create group by column definitions
  for (const auto& column_id : _groupby_column_ids) {
    _output_column_definitions.emplace_back(input_table->column_name(column_id),
                                            input_table->column_data_type(column_id),
                                            input_table->column_is_nullable(column_id));
  }

  // Create aggregate column definitions
  ColumnID aggregate_idx{0};
  for (const auto& aggregate : _aggregates) {
    const auto& pqp_column = static_cast<const PQPColumnExpression&>(*aggregate->argument());
    const auto column_id = pqp_column.column_id;

    /*
     * Special case for COUNT(*), which is the only case where column equals INVALID_COLUMN_ID:
     * Usually, the data type of the aggregate can depend on the data type of the corresponding input column.
     * For example, the sum of ints is an int, while the sum of doubles is a double.
     * For COUNT(*), the aggregate type is always Long, regardless of the input type.
     * As the input type does not matter and we do not even have an input column,
     * but the function call expects an input type, we choose Long to be consistent with the output type.
     */
    const auto data_type = column_id == INVALID_COLUMN_ID ? DataType::Long : input_table->column_data_type(column_id);

    resolve_data_type(data_type, [&, aggregate_idx](auto type) {
      _create_aggregate_column_definitions(type, aggregate_idx, aggregate->aggregate_function);
    });

    ++aggregate_idx;
  }

  auto result_table = std::make_shared<Table>(_output_column_definitions, TableType::Data);

  /*
   * Handle empty input table according to the SQL standard
   *  if group by columns exist -> empty result
   *  else -> one row with default values
   *
   * TODO(anyone) this code could probably be shared by the aggregate implementations.
   * As of now, the hash aggregate handles this edge case in write_aggregate_output().
   * However, HashAggregate::write_aggregate_output writes both agggregate column definitions and actual values.
   * Separating those two steps would allow us to reuse AggregateSort::create_aggregate_column_definitions(),
   * as well as the code below.
   */
  if (input_table->empty()) {
    if (_groupby_column_ids.empty()) {
      std::vector<AllTypeVariant> default_values;
      for (const auto& aggregate : _aggregates) {
        if (aggregate->aggregate_function == AggregateFunction::Count ||
            aggregate->aggregate_function == AggregateFunction::CountDistinct) {
          default_values.emplace_back(int64_t{0});
        } else {
          default_values.emplace_back(NULL_VALUE);
        }
      }
      result_table->append(default_values);
    }

    return result_table;
  }

  std::shared_ptr<const Table> sorted_table = input_table;
  if (!_groupby_column_ids.empty()) {
    /**
    * If there is a value clustering for a column, it means that all tuples with the same value in that column are in
    * the same chunk. Therefore, if one of the value clustering columns is part of the group by vector, we can skip
    * sorting the whole table and sort on a per-chunk basis instead. Values that would end up in the same cluster are
    * already in the same chunk. In the current definition of value clustering, NULL values must not occur.
    *
    * If the value clustering doesn't match the columns we group by, we need to sort the whole table to achieve the
    * consecutiveness of equal values we need (table-wide sort information is not tracked yet).
    */
    const auto& table_value_clustered_by = input_table->value_clustered_by();
    auto is_value_clustered_by_groupby_column = false;

    if (!table_value_clustered_by.empty()) {
      for (const auto& value_clustered_by : table_value_clustered_by) {
        if (std::find(_groupby_column_ids.begin(), _groupby_column_ids.end(), value_clustered_by) !=
            _groupby_column_ids.end()) {
          is_value_clustered_by_groupby_column = true;
          break;
        }
      }
    }

    if (is_value_clustered_by_groupby_column) {
      // Sort input table chunk-wise as the group by values are clustered.
      sorted_table = _sort_table_chunk_wise(input_table, _groupby_column_ids);
    } else {
      sorted_table = sort_table_by_column_ids(input_table, _groupby_column_ids);
    }
  }

  _output_segments.resize(_aggregates.size() + _groupby_column_ids.size());

  /*
   * Find all RowIDs where a value in any group by column changes compared to the previous row,
   * as those are exactly the boundaries of the different groups.
   * Everytime a value changes in any of the group by columns, we add the current position to the set.
   * We are aware that std::set is known to be not the most efficient,
   * but our profiling revealed that the current implementation is not a bottleneck.
   * Currently, the vast majority of execution time is spent with sorting.
   * Moreover, this set grows only to O(output) many elements, so inserts and lookups should stay reasonably fast.
   *
   *
   * If this does become a performance problem at some point, one could try e.g. a vector of vectors,
   * with one vector per column.
   * Each vector stores all RowIDs where the corresponding column changes.
   * Afterwards, the vectors have to be merged and deduplicated (presorted list merge).
   * We have not benchmarked this solution, so we do not know how it performs in comparison to the current one.
   *
   * General note: group_boundaries contains the first entry of a new group,
   *               or in other words: the last entry of a group + 1 row, similar to vector::end()
   *
   *               It is (in _aggregate_values) used as indicator that a group has ended just before this row.
   *               As a result, the start of the very first group is not represented in group_boundaries,
   *               as there was no group before that ended.
   *               Further, the end of the last group is not represented as well.
   *               This is because no new group starts after it.
   *               So in total, group_boundaries will contain one element less than there are groups.
   */
  std::set<RowID> group_boundaries;
  const auto chunk_count = sorted_table->chunk_count();
  for (const auto& column_id : _groupby_column_ids) {
    auto data_type = input_table->column_data_type(column_id);
    resolve_data_type(data_type, [&](auto type) {
      using ColumnDataType = typename decltype(type)::type;
      std::optional<ColumnDataType> previous_value;

      /*
       * Initialize previous_value to the first value in the table, so we avoid considering it a value change.
       * We do not want to consider it as a value change, because we the first row should not be part of the boundaries.
       * For the reasoning behind it see above.
       * We are aware that operator[] is slow, however, for one value it should be faster than segment_iterate_filtered.
       */
      const auto& first_segment = sorted_table->get_chunk(ChunkID{0})->get_segment(column_id);
      const auto& first_value = (*first_segment)[ChunkOffset{0}];
      if (variant_is_null(first_value)) {
        previous_value.reset();
      } else {
        previous_value.emplace(boost::get<ColumnDataType>(first_value));
      }

      // Iterate over all chunks and insert RowIDs when values change
      for (auto chunk_id = ChunkID{0}; chunk_id < chunk_count; ++chunk_id) {
        const auto chunk = sorted_table->get_chunk(chunk_id);
        Assert(chunk, "Physically deleted chunk should not reach this point, see get_chunk / #1686.");
        const auto& segment = chunk->get_segment(column_id);
        segment_iterate<ColumnDataType>(*segment, [&](const auto& position) {
          if (previous_value.has_value() == position.is_null() ||
              (previous_value.has_value() && !position.is_null() && position.value() != *previous_value)) {
            group_boundaries.insert(RowID{chunk_id, position.chunk_offset()});
            if (position.is_null()) {
              previous_value.reset();
            } else {
              previous_value.emplace(position.value());
            }
          }
        });
      }
    });
  }

  /*
   * For all group by columns
   *   For each group by column
   *     output the column value at the start of the group (it is per definition the same in the whole group)
   * Write outputted values into the result table
   */
  const auto write_groupby_column = [&](const ColumnID input_column_id, const ColumnID output_column_id) {
    const auto column_is_nullable = _output_column_definitions.at(output_column_id).nullable;
    auto group_boundary_iter = group_boundaries.cbegin();
    auto data_type = input_table->column_data_type(input_column_id);
    resolve_data_type(data_type, [&](auto type) {
      using ColumnDataType = typename decltype(type)::type;
      auto values = pmr_vector<ColumnDataType>(group_boundaries.size() + 1);
      auto null_values = pmr_vector<bool>(column_is_nullable ? group_boundaries.size() + 1 : 0);

      for (size_t value_index = 0; value_index < values.size(); value_index++) {
        RowID group_start;
        if (value_index == 0) {
          // First group starts in the first row, but there is no corresponding entry in the set. See above for reasons.
          group_start = RowID{ChunkID{0}, ChunkOffset{0}};
        } else {
          group_start = *group_boundary_iter;
          group_boundary_iter++;
        }

        const auto chunk = sorted_table->get_chunk(group_start.chunk_id);
        const auto& segment = chunk->get_segment(input_column_id);

        /*
         * We are aware that operator[] and AllTypeVariant are known to be inefficient.
         * However, for accessing a single value it is probably more efficient than segment_iterate_filtered,
         * besides being more readable.
         * We cannot use segment_iterate_filtered with the whole group_boundaries (converted to a PosList).
         * This is because the RowIDs in group_boundaries can reference multiple chunks.
         */
        const auto& value = (*segment)[group_start.chunk_offset];

        DebugAssert(!variant_is_null(value) || column_is_nullable, "Null values found in non-nullable column");
        if (variant_is_null(value)) {
          null_values[value_index] = true;
        } else {
          values[value_index] = boost::get<ColumnDataType>(value);
        }
      }

      // Write group by segments
      if (column_is_nullable) {
        _output_segments[output_column_id] =
            std::make_shared<ValueSegment<ColumnDataType>>(std::move(values), std::move(null_values));
      } else {
        _output_segments[output_column_id] = std::make_shared<ValueSegment<ColumnDataType>>(std::move(values));
      }
    });
  };

  auto groupby_output_column_id = ColumnID{0};
  for (const auto& input_column_id : _groupby_column_ids) {
    write_groupby_column(input_column_id, groupby_output_column_id);
    ++groupby_output_column_id;
  }

  // Call _aggregate_values for each aggregate
  uint64_t aggregate_index = 0;
  for (const auto& aggregate : _aggregates) {
    /*
     * Special case for COUNT(*), which is the only case where aggregate.column equals INVALID_COLUMN_ID:
     * Usually, the data type of the aggregate can depend on the data type of the corresponding input column.
     * For example, the sum of ints is an int, while the sum of doubles is an double.
     * For COUNT(*), the aggregate type is always an integral type, regardless of the input type.
     * As the input type does not matter and we do not even have an input column,
     * but the function call expects an input type, we choose Int arbitrarily.
     * This is NOT the result type of COUNT(*), which is Long.
     */
    const auto& pqp_column = static_cast<const PQPColumnExpression&>(*aggregate->argument());
    const auto input_column_id = pqp_column.column_id;

    const auto data_type =
        input_column_id == INVALID_COLUMN_ID ? DataType::Long : input_table->column_data_type(input_column_id);
    resolve_data_type(data_type, [&](auto type) {
      using ColumnDataType = typename decltype(type)::type;

      /*
       * We are aware that the switch looks very repetitive, but we could not find a dynamic solution.
       * The problem we encountered: We cannot simply hand aggregate->aggregate_function into the call of _aggregate_values.
       * The reason: the compiler wants to know at compile time which of the templated versions need to be called.
       * However, aggregate->aggregate_function is something that is only available at runtime,
       * so the compiler cannot know its value and thus not deduce the correct method call.
       */
      switch (aggregate->aggregate_function) {
        case AggregateFunction::Min: {
          using AggregateType = typename AggregateTraits<ColumnDataType, AggregateFunction::Min>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::Min>(group_boundaries, aggregate_index,
                                                                                sorted_table);
          break;
        }
        case AggregateFunction::Max: {
          using AggregateType = typename AggregateTraits<ColumnDataType, AggregateFunction::Max>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::Max>(group_boundaries, aggregate_index,
                                                                                sorted_table);
          break;
        }
        case AggregateFunction::Sum: {
          using AggregateType = typename AggregateTraits<ColumnDataType, AggregateFunction::Sum>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::Sum>(group_boundaries, aggregate_index,
                                                                                sorted_table);
          break;
        }

        case AggregateFunction::Avg: {
          using AggregateType = typename AggregateTraits<ColumnDataType, AggregateFunction::Avg>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::Avg>(group_boundaries, aggregate_index,
                                                                                sorted_table);
          break;
        }
        case AggregateFunction::Count: {
          using AggregateType = typename AggregateTraits<ColumnDataType, AggregateFunction::Count>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::Count>(group_boundaries, aggregate_index,
                                                                                sorted_table);
          break;
        }
        case AggregateFunction::CountDistinct: {
          using AggregateType = typename AggregateTraits<
              ColumnDataType, AggregateFunction::CountDistinct>::AggregateType;  // NOLINT(whitespace/line_length)
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::CountDistinct>(
              group_boundaries, aggregate_index, sorted_table);
          break;
        }
        case AggregateFunction::StandardDeviationSample: {
          using AggregateType =
              typename AggregateTraits<ColumnDataType, AggregateFunction::StandardDeviationSample>::AggregateType;
          _aggregate_values<ColumnDataType, AggregateType, AggregateFunction::StandardDeviationSample>(
              group_boundaries, aggregate_index, sorted_table);
          break;
        }
        case AggregateFunction::Any: {
          write_groupby_column(input_column_id, ColumnID{static_cast<ColumnID::base_type>(aggregate_index +
                                                                                _groupby_column_ids.size())});
          break;
        }
      }
    });

    aggregate_index++;
  }

  // Append output to result table
  if (_output_segments.at(0)->size() > 0) {
    result_table->append_chunk(_output_segments);
  }

  // We do not set sort information on the output table as we can only guarantee it in certain situations (e.g., when
  // the whole input table needed to be sorted). As this aggregate case is the fall back solution and should be rather
  // be calculated with the hash aggregate, we neglect the sort information for now and keep it simple.
  return result_table;
}

std::shared_ptr<AbstractOperator> AggregateSort::_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<AggregateSort>(copied_left_input, _aggregates, _groupby_column_ids);
}

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

void AggregateSort::_on_cleanup() {}

template <typename ColumnType>
void AggregateSort::_create_aggregate_column_definitions(boost::hana::basic_type<ColumnType> type,
                                                         ColumnID column_index, AggregateFunction aggregate_function) {
  /*
   * We are aware that the switch looks very repetitive, but we could not find a dynamic solution.
   * There is a similar switch statement in _on_execute for calling _aggregate_values.
   * See the comment there for reasoning.
   */
  switch (aggregate_function) {
    case AggregateFunction::Min:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Min>(column_index);
      break;
    case AggregateFunction::Max:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Max>(column_index);
      break;
    case AggregateFunction::Sum:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Sum>(column_index);
      break;
    case AggregateFunction::Avg:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Avg>(column_index);
      break;
    case AggregateFunction::Count:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Count>(column_index);
      break;
    case AggregateFunction::CountDistinct:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::CountDistinct>(column_index);
      break;
    case AggregateFunction::StandardDeviationSample:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::StandardDeviationSample>(column_index);
      break;
    case AggregateFunction::Any:
      create_aggregate_column_definitions<ColumnType, AggregateFunction::Any>(column_index);
      break;
  }
}

/*
 * TODO(anyone) this function could be shared by the aggregate implementations.
 *
 * Most of this function is copied from HashAggregate::write_aggregate_output().
 * However, the function in the hash aggregate does more than just creating aggregate colum definitions.
 * As the name says, it also writes the aggregate output (values),
 *  which the sort aggregate already does in another place.
 * To reduce code duplication, the hash aggregate could be refactored to separate creating column definitions
 *  and writing the actual output.
 *  This would also allow to reuse the code for handling an empty input table (see _on_execute()).
 */
template <typename ColumnType, AggregateFunction aggregate_function>
void AggregateSort::create_aggregate_column_definitions(ColumnID column_index) {
  // retrieve type information from the aggregation traits
  auto aggregate_data_type = AggregateTraits<ColumnType, aggregate_function>::AGGREGATE_DATA_TYPE;

  const auto& aggregate = _aggregates[column_index];
  const auto& pqp_column = static_cast<const PQPColumnExpression&>(*aggregate->argument());
  const auto input_column_id = pqp_column.column_id;

  if (aggregate_data_type == DataType::Null) {
    // if not specified, it's the input column's type
    aggregate_data_type = left_input_table()->column_data_type(input_column_id);
  }

  const auto nullable =
      (aggregate_function != AggregateFunction::Count && aggregate_function != AggregateFunction::CountDistinct &&
       aggregate_function != AggregateFunction::Any) ||
      (aggregate_function == AggregateFunction::Any && left_input_table()->column_is_nullable(input_column_id));
  const auto column_name = aggregate->aggregate_function == AggregateFunction::Any ? pqp_column.as_column_name()
                                                                                : aggregate->as_column_name();
  _output_column_definitions.emplace_back(column_name, aggregate_data_type, nullable);
}
}  // namespace hyrise

redpajama_set_name: RedPajamaGithub


text:
/Here's Why ...
Here's Why Adam Lambert Doesn't Think Theo James Should Play George Michael in a Biopic
The White Lotus star Theo James joined Watch What Happens Live last week, where he expressed interest in playing George Michael if a biopic were ever in the works.
"Oh yeah, I would love that, he's an icon," he said. "He's a lot of Greek, and I'm a lot of Greek. Put that Greek together, and you get falafel."
However, when The Advocate shared the news to Instagram, Adam Lambert criticized the thought. "Yay another straight man playing a gay icon," the singer commented, along with an eye roll emoji. The comment was seemingly in reference to other biopics about gay stars played by straight men, such as Rami Malek playing Freddie Mercury in Bohemian Rhapsody and Taron Egerton playing Elton John in Rocketman.
However, despite reports of a biopic surrounding the late Wham! frontman, the George Michael estate put to rumors to rest in a statement. "To all of George's Lovelies, fans and lovers of his music, a story has been published stating that George Michael's family has endorsed a so called 'biopic' about his life," read the note from George Michael Entertainment. "On behalf of George's family and GME we want to make it clear that there is no truth whatsoever in this story, we know nothing about this project and will not be endorsing it in any way."

redpajama_set_name: RedPajamaCommonCrawl


Indexed and variable annuity sales got crushed in the first quarter, thanks to the DOL fiduciary rule, reports InvestmentNews.
VA sales fell 8% in the quarter compared to the year-earlier period, to $24.4 billion, according to Limra. Indexed annuity sales fell 13%, to $13.6 billion.
Sales slid even against a backdrop of a cooperative stock market and interest rates. When the fiduciary rule goes into effect—it's scheduled to do so on June 9—thousands of brokers and insurance agents will become legal fiduciaries.
"All of the rule's provisions, including one that increases litigation risk for advisers and their supervisory firms for selling certain products such as indexed and variable annuities, will come into force in 2018," InvestmentNews notes.
Those who sell the products are hoping the fiduciary rule is further delayed, or is revised to protect them from the risk of lawsuits.
"I think somewhat with the uncertainty out there, that's impacting sales," Todd Giesing, assistant research director at the Limra Secure Retirement Institute, tells InvestmentNews.


Representing native, not-for-profit, publicly governed managed health care plans throughout the state. Anthem's departure can also be a blow for the Coated California change, which has typically boasted that wholesome competition amongst its plans helped lower costs and enhance its members' access to care. We offer skilled recommendation and we may help you apply for particular person and group health plan. POS (point of service): You may see doctors and go to a hospital exterior of your plan's network at an additional cost.
By insuring a big group of staff together below one plan of the company's selecting, particular person workers are usually not topic to medical underwriting; reasonably your entire group is underwritten as a complete to determine the premium level everybody will pay. Years of working within the medical subject have taught me how very important it is to have quality Well being Insurance. We don't know but how that scenario shall be lined in 2014, however right now, the maternity and supply costs won't be lined by your health insurance.
In simply three years, Alliance has diminished medical costs by more than $19 million, in comparison with a traditional HMO plan. As of January 1, 2014, most U.S. citizens and legal residents are required by legislation to have qualifying health care coverage or pay an annual tax penalty for every month they go without insurance. Because that would invite disputes, California has pointers that have been established as to the definition of affordable." As a common rule, the price of health insurance is taken into account affordable if it doesn't exceed 5% of the father or mother's gross revenue.
No, the Well being Companies Price does not qualify as medical health insurance.
Covered California is California's medical insurance marketplace created by the Inexpensive Care Act (ACA). COBRA health insurance requires that coverage, when it comes to advantages, deductibles, and coverage limits, be similar to similarly situated lively plan members. Each is based on the typical amount of healthcare costs the plan will cover shown as a proportion of what is covered by your insurance firm and what's paid for by you. Within minutes you may receive a free medical insurance quote on-line and select a health plan that meets your funds.
Now that you are signed up for updates from Covered California, we'll send you ideas and reminders to help together with your well being coverage. Nevertheless, public protection might pay for some providers that many personal plans don't cowl like transportation, non-public-responsibility nursing , and Personal Care Assistant (PCA) services. The California Continuation Benefits Alternative Act (Cal-COBRA) specifies the quantity a certified beneficiary may be charged for continuation protection, how long the continuation protection can last, and when protection can be terminated.
Family Physicians, the American Benefits Council, the American Hospital Association, the American Medical Association, the Blue Cross Blue Defend Affiliation, the Federation of American Hospitals and the U.S. Chamber of Commerce. Maryland lawmakers, for instance, are attempting to undertake a mandate that residents have medical health insurance or pay a penalty. For prime-deductible health plans, the copay restrict will apply after the deductible has been met (Lined California already applied the same restriction , starting in 2016).
It qualifies health plans offering coverage via it - (certifying, recertifying and decertifying). Tax credit are only accessible to California residents who purchase coverage from Coated California. You'll have to pay a Tax Penalty if you file your taxes if you should not have health insurance or an exemption. It's a revolutionary improvement to maneuver from a broken market where persons are charged by how sick they are, to a competitive market where folks pay what they'll afford, based mostly on a percentage of their income, on a sliding scale," stated Anthony Wright, government director of advocacy group Well being Access.
Equally, the Easy Silver has $7,350 maximum out-of-pocket amount and 6 health care services with a set copayment resembling office visits at $25.


If you are one of the millions of women who desire a smooth, radiant complexion, you may want to examine your skin to see if it would benefit from an exfoliation. Exfoliation is a skin care procedure that involves the removal of aged surface skin cells that make your skin appear lifeless and dull. It's a procedure that is easy to do. To determine if dead skin is preventing you from having the beautiful young looking skin you desire, and to help you decide whether or not your skin needs exfoliating, check to see if your skin shows any of the signs listed below.
Stroke your face with the pads on your fingers and take note of what you feel. If you don't feel soft, smooth skin, what you may be feeling is scaly skin that should be sloughed off so that the nourishing and hydrating face creams you apply to your face can seep into the pores beneath it and do their job. Silky skin is what you want to feel, and exfoliation is the way to get it.
If you see that your pores are congested or plugged up with blackheads, extraction of the impurities in your pores is necessary if you want to improve the appearance of your skin. Exfoliation prior to extraction makes extraction easier. It produces more satisfactory results once the dead skin is removed from the top of the pore opening.
It is true wrinkles come with age and make you look old, but what is also true is old skin that remains on your face makes you look years older too because it accentuates wrinkles. Old skin cells settle in crevices and make wrinkles appear deeper. If you notice more lines on your face than usual, exfoliation should help.
Should your skin analysis bring you to the conclusion exfoliation is warranted, the suggestion is to use an exfoliant that also serves as a mask. Choose one that fits your skin type. Dry skin will especially benefit from an exfoliating mask because masks designed for dry skin usually contain hydrating ingredients.
Caution: Do not exfoliate over moles or broken skin. Also avoid exfoliating skin if you have a skin disease. Follow the directions printed on the product you use, and never rub your skin with great force.
My skin is Exfoliating and i just wanted to confirm it. After reading your blog on the signs of Exfoliating an am sure about it. Your blog is really very helpful for me. Keep sharing!
Nice post.Thanks for sharing.It gives us great information regarding skin care..
The information you shared about the dry skin is very useful for me and these three way you tell us is to examine skin that was also very useful for me thanks ..
I am pleased by reading this valuable tips for skin care. Can you please some more for dry hairs?
Very impressed with your blog. I want to do permanent treatment and this blog is very helpful for me. Please share me its process it will very helpful for me.
the best time to exfoliate is in the morning. Apparently, our skin repairs itself at night therefore the morning is the perfect time for scrubbing away those dead skin cells.
After reading your post I have got lots of knowledge Exfoliation. The way you have explained it is very easy.
These tips and advices for skin are really very much effective. Keep it up with sharing such useful information with us. Thanks for the post.
Such information is not usually available on the blogs, and I like the way of yours in creating such a blog and helping the concerned readers.Keep uploading more.
Now, I can identify the Exfoliation on my skin after reading your post and I really appreciate the all impressive points that you have discussed.
Exfoliation involves the removal of the oldest dead skin cells on the skin's outermost surface, and has been used for many years to help maintain skin.
To determine if dead skin is preventing you from having the beautiful young looking skin you desire, and to help you decide whether or not your skin needs exfoliating, check to see if your skin shows any of the signs listed below.
Skin cleansing, toning, moisturizing and conditioning helps to clean skin pores and exfoliate the dead cells. Diet, deep breathing exercises also help in glowing skin.
Hey, Great skin care points you have shared to support women's skin. Thanks for your healthy support.
You have mention nice guidelines for skin care. It's simple, to the point and informative.I appreciate your hard work and dedication. Good luck and keep sharing your views.
I liked your information over skin examination. I liked the way you detailed everything on it. Keep sharing such guidelines.
Wow nice post! Thanks for sharing it.In your post i found very good tip for skin care.keep sharing another post.
Good work…unique site and interesting too… keep it up…looking forward for more updates.Please share more n more blog.
Useful content. I really like your cool & cool website. Many many thanks for sharing your useful topic. Lets go...!!!!!
Our marvelous Panerai Ferrari 8 Days Fake Replica can also bring you same distinguished charming as genuine ones. Come to join us now, you won't be regret!
Nice post! You have defined important tips to deal with damaged skin problem. Hope these tips really give me better result. It will also help me to look beautiful. Thanks for sharing such important information.
You're sharing some great and important point which is very important for each and every people who want to care of their skin.
You have beautifully covered many tips and suggestions regarding skin exfoliating. I want to appreciate your writing skill. thanks for such an impressive post.
The post is written in very a good manner and it entails much useful information for me. I am happy to find your distinguished way of writing the post. Thanks.
Notification letters are being issued to the affected owners, and full costs of the inspection and repairs will naturally be borne by MMM.
I must say that I really enjoyed reading all of Your posts. Thanks for taking the time to discuss this, I feel strongly about it and love learning more on this topic.
Now, can we go back to some basics? How much Online casino is needed to do anything so far? Consummate media distorting headline.
Interesting. Still. I'd ask why? I'm fed up with the illogical pantomime of Online casino. I GIVE UP. Thanks for reading.
Simply favorable post, the way you have shared the details on the skin care is of high notch for me. I think you have supplied lot of details on this subject.
Clear and depictive blog I would say. The way you have come up with the concept on this is prime and supreme for me.
They say good stuff come in small offers and you shown it here in your brief and simple brief article. This brief article is appropriate and to the point. I suggest it to everyone viewing this weblog.
Every magazine, tabloid, and infomercial seems to have a million of these skin care tips to offer you. The problem is that I see and hear things that are not covering the fundamental needs of the consumer. When I hear these people offer a skin care tip I often cringe.
more secure and protect doors, the more?
you may want to read?
it will be worth to seek for?
the majority folks created our "1st compensation feeling Free" supply primarily as a results of our suggests that of in search of to shop for your liability in conjunction with feel in round the business. U.S. of America ALL day money enhancements is okay to help you purchase your current liability, just by galvanized to form around each acknowledging comprehensive sizzling what's a lot of hospitable, swiftly, respectful, in conjunction with useful. Confine mind, my business is throughout this posting that's able to facilitate our purchasers utilizing short-term affordable needs, equally as all folks shall screen the merchandise for yourself on each occasion someone facilitate men and ladies.
Were during this posting to help you at the side of your short-run financial needs. The actual amount is a wonderful product and services that might can permit various men and ladies, as you, day-to-day! Anytime emergencies happen, don't anxiety! Occur notice all people. We've got been typically there to fit your desires and additionally all people judge encouraging someone at the side of your financial needs.
Payday money advances, day and fitting money loans, besides to Automobile construct money loans. The majority focus on aiding you decide on for the correct loan product or service that may assist you to satisfy your own economic needs.
Anytime issues invest in hard then you 'must' have further resources, having obtaining some variety of plan loan is that the higher vogue concerning loan to fit your wants. You get what proportion cash you may want; anyone retain your automobile in conjunction with most people primarily help this subject toward automotive before disposition choices are obtained fully, wherever ever event this specific topic are flip back for yourself cost-free in conjunction with apparent. It may be that easy.
the World wide web with this topic?
which are often very alone?
decorations as well as eliminate any day?
too a lot of attention?
and you will then see many?
decoration to make sure you remember?
clip body including a nice?
you might choose to read?
My skin is Exfoliation and i just wanted to validate it. Looking at your weblog site on symptoms and symptoms of Exfoliation an am sure about it. Your weblog is really very helpful for me.


text:
Page 3 from 2791 < 1 2 3 4 5 6 7 13 2791 >
41 A point moves in the plane so that its tangential acceleration wτ = a, and its normal acceleration wn = bt4, where a and b are positive constants, and t is time. At the moment t = 0 the point was at rest. Find how the curvature radius R of the point s trajectory and the total acceleration w depend on the distance covered s.
42 A particle moves along the plane trajectory y(x) with velocity v whose modulus is constant. Find the acceleration of the particle at the point x = 0 and the curvature radius of the trajectory at that point if the trajectory has the form (a) of a parabola y = ax2; (b) of an ellipse (x/a)2 + (y/b)2 = 1; a and b are constants here.
43 A particle A moves along a circle of radius R = 50 cm so that its radius vector r relative to the point O (Fig. 1.5) rotates with the constant angular velocity ω = 0.40 rad/s. Find the modulus of the velocity of the particle, and the modulus and direction of its total acceleration.
44 A wheel rotates around a stationary axis so that the rotation angle φ varies with time as φ = at2, where a = 0.20 rad/s2. Find the total acceleration w of the point A at the rim at the moment t = 2.5 s if the linear velocity of the point A at this moment v = 0.65 m/s.
45 A shell acquires the initial velocity v = 320 m/s, having made n = 2.0 turns inside the barrel whose length is equal to l = 2.0 m. Assuming that the shell moves inside the barrel with a uniform acceleration, find the angular velocity of its axial rotation at the moment when the shell escapes the barrel.
46 A solid body rotates about a stationary axis according to the law φ = at - bt3, where a = 6.0 rad/s and b = 2.0 rad/s3. Find: (a) the mean values of the angular velocity and angular acceleration averaged over the time interval between t = 0 and the complete stop; (b) the angular acceleration at the moment when the body stops.
47 A solid body starts rotating about a stationary axis with an angular acceleration β = at, where a = 2.0*10-2 rad/s3. How soon after the beginning of rotation will the total acceleration vector of an arbitrary point of the body form an angle α = 60° with its velocity vector?
48 A solid body rotates with deceleration about a stationary axis with an angular deceleration β ∼ sqrt(ω) where ω is its angular velocity. Find the mean angular velocity of the body averaged over the whole time of rotation if at the initial moment of time its angular velocity was equal to ω0.
49 A solid body rotates about a stationary axis so that its angular velocity depends on the rotation angle φ as ω = ω0 - aφ, where ω0 and a are positive constants. At the moment t = 0 the angle φ = 0. Find the time dependence of (a) the rotation angle; (b) the angular velocity.
50 A solid body starts rotating about a stationary axis with an angular acceleration β = β0 cos φ, where β0 is a constant vector and φ is an angle of rotation from the initial position. Find the angular velocity of the body as a function of the angle φ. Draw the plot of this dependence.
51 A rotating disc (Fig. 1.6) moves in the positive direction of the x axis. Find the equation y(x) describing the position of the instantaneous axis of rotation, if at the initial moment the axis C of the disc was located at the point O after which it moved (a) with a constant velocity v, while the disc started rotating counterclockwise with a constant angular acceleration β (the initial angular velocity is equal to zero); (b) with a constant acceleration w (and the zero initial velocity), while the disc rotates counterclockwise with a constant angular velocity ω.
52 A point A is located on the rim of a wheel of radius R = 0.50 m which rolls without slipping along a horizontal surface with velocity v = 1.00 m/s. Find: (a) the modulus and the direction of the acceleration vector of the point A; (b) the total distance s traversed by the point A between the two successive moments at which it touches the surface.
53 A ball of radius R = 10.0 cm rolls without slipping down an inclined plane so that its center moves with constant acceleration w = 2.50 cm/s2; t = 2.00 s after the beginning of motion its position corresponds to that shown in Fig. 1.7. Find: (a) the velocities of the points A, B, and O; (b) the accelerations of these points.
54 A cylinder rolls without slipping over a horizontal plane. The radius of the cylinder is equal to r. Find the curvature radii of trajectories traced out by the points A and B (see Fig; 1.7).
55 Two solid bodies rotate about stationary mutually perpendicular intersecting axes with constant angular velocities ω1 = 3.0 rad/s and ω2 = 4.0 rad/s. Find the angular velocity and angular acceleration of one body relative to the other.
56 A solid body rotates with angular velocity ω = ati + bt2j, where a = 0.50 rad/s2, b = 0.060 rad/s3, and i and j are the unit vectors of the x and y axes. Find: (a) the moduli of the angular velocity and the angular acceleration at the moment t = 10.0 s; (b) the angle between the vectors of the angular velocity and the angular acceleration at that moment.
57 A round cone with half-angle α = 30° and the radius of the base R = 5.0 cm rolls uniformly and without slipping over a horizontal plane as shown in Fig. 1.8. The cone apex is hinged at the point O which is on the same level with the point C, the cone base centre. The velocity of point C is v = 10.0 cm/s. Find the moduli of (a) the vector of the angular velocity of the cone and the angle it forms with the vertical; (b) the vector of the angular acceleration of the cone.
58 A solid body rotates with a constant angular velocity ω0 = 0.50 rad/s about a horizontal axis AB. At the moment t = 0 the axis AB starts turning about the vertical with a constant angular acceleration β0 = 0.10 rad/s2. Find the angular velocity and angular acceleration of the body after t = 3.5 s.
59 An aerostat of mass m starts coming down with a constant acceleration w. Determine the ballast mass to be dumped for the aerostat to reach the upward acceleration of the same magnitude. The air drag is to he neglected.
60 In the arrangement of Fig. 1.9 the masses m0, m1, and m2 of bodies are equal, the masses of the pulley and the threads are negligible, and there is no friction in the pulley. Find the acceleration w with which the body m0 comes down, and the tension of the thread binding together the bodies m1 and m2, if the coefficient of friction between these bodies and the horizontal surface is equal to k. Consider possible cases.


These programs are provided to you free as a service of Caduceus Digital Systems to the community of users. We hope you find the programs useful. Ignore the "BUY" on the button and just click it to process your free download. Thanks!


When a patient has a sperm disorder a Chinese Medicine practitioner will first check to see if an infection or tumour is involved, or if the testicles have descended. These conditions must be treated first. When a low sperm count is the problem, Chinese herbs to strengthen and tonify the kidneys will improve this condition. A wide variety of herbs can be used to help, but the cause may vary from kidney essence to a deficiency of kidney yang or kidney yin, with a different form of treatment in each case.


My favorite thing about starting a new year is how fresh and hopeful everything feels. I really, really would have liked to start the 2015 blogging year by being all caught up on my reviews, but, well, yeah ... didn't happen. I'm still woefully behind (evidence: the last book I reviewed was one I read in August)! Shame on me. As far as blogging resolutions, I'm going for the same ole, same ole (as unattainable as they may be): catch up on reviews, keep up on reviews, and try to read 200 books this year. That's it. We'll see how I do.
In comparison with 2013, I read more non-fiction this year, more adult novels, more of my own books and more books from the library. Wow. Does that mean I've matured a little since last year? Surprisingly, I read fewer review books this year. Not by many, but still ... interesting.
How about you? How did your reading year go? What were your favorite reads of 2014? I love end-of-the-year lists/surveys, so let me know if you've got one up on your blog. I'd love to come take a look!
Thanks for all the love you've given my blog this year. It makes me so happy to read your comments, check out your book recommendations, and hop around to your blogs. Here's to another great year of bloggin' 'bout books!
P.S. Before I delete the list of books I read in 2014 from the bottom of my blog, I'm going to list them here. Asterisks denote favorites.
Wow! 139 books is awesome! Way to go! I posted my end of the year stats yesterday but they were nowhere near as impressive as yours.
Awesome list! I don't know how you do it! I've got my numbers up on my blog today too. :) Not nearly as impressive though.
Great list. I get a lot of my book ideas from you. Thank you!
Happy New Year to you, Susan! 139 books is a lot and your goal is 200 for 2015. Good luck to you!
I'm reentering the blogging world and saying hello to friends that I've met in the past. I invite you to visit me at my new blog - kay's reading life. Looking forward to chatting books, life, and other assorted topic with you. I've missed it!
Good for you! I was pleasantly surprised to find I'd read 52 books in 52 weeks--not at a steady rate, but it sounds good!
What a great year for you! Even if it was a few books shy of the total last year. Wonder how they'd stack up if you measured by page numbers?
Hope that 2015 is a GREAT year for you!


A Community Based Patrol can be everything from a trained group of volunteers, to an organized group of security professionals utilized to increase the safety and quality of life in a neighborhood.
Using a variety of patrol methods (i.e. vehicle, foot, bicycle, etc.) streets, parks, or schools are patrolled at target hours to deter crime and report incidents and problems to local officials. With limited resources supported by local, state and federal governments, rather than sit back and hope that someone else will take care of a community condition, members are actively and directly involved in solving problems in a community-based, non-confrontational manner.
Community Based Patrols collaborate with municipalities, crime prevention coordinators, urban planners, police, neighborhood coalitions and associations, and area businesses to help neighborhood problems receive prompt and effective attention.
Neighborhood association preserving and protecting upper Manhattan's most attractive and varied neighborhoods.
Homeowners association in Suffolk County, Long Island, NY.
Seaview is a family-oriented seasonal community of approximately 360 homes, located in the central portion of Fire Island. Seaview Association is an incorporated not-for-profit Homeowners Association (501 C-4), that owns and/or maintains the community's sidewalks, beaches, and common areas.
Exclusive beach community in Connecticut.
Located on Fire Island, Summer Club is a small exclusive community located just west of Ocean Beach.


text:
The Last of Us TV series: when is it coming out in Italian? Spaziogames.it
The Last of Us TV series: when is it coming out with Italian subs?
The dates of the episodes with Italian subtitles
The Last of Us TV series: when will it be out dubbed in Italian?
The dates of the episodes dubbed in Italian
there The TV series The Last of Us is one of the most eagerly awaited dates in early 2023. We've known that ever since January 16, 2023 The first official episode has also arrived in Italy, but there is still confusion as many readers ask us when they can expect the subtitled episodes and when the series will come out instead entirely in Italian, dubbing included.
We then decided to clear things up and help you with a quick guide that can fully answer your questions.
As with other major HBO productions (like Game of Thrones and House of the Dragon) Sky Atlantic and TV now (his streaming correspondent) also allows you Follow the series simultaneously with the United States.
This means new episodes are arriving 3:00 a.m. on Monday in Italy, while in the United States they are Sunday prime time.
The TV series Last of Us also appears in Italian: let's see all the dates
Upcoming episodes at the same time as the United States but they are what they are Italian subtitles only. They will then be transferred the original English version. If you don't have problems with the native language of the production, you can enjoy it in peace as soon as it arrives, so as not to risk spoilers from social networks and the American public.
Below are therefore the dates of the nine episodes and their release with Italian subtitles:
episode 1: January 16, 03:00
Episode 4: 6 February, 03.00
episode 5: February 13, 03.00
episode 8: March 6, 03:00
episode 9: March 13, 03:00
As you can see, HBO, and by extension Sky Atlantic, uses a weekly delivery model and doesn't release all episodes at the same time like productions from other networks – like Netflix – do.
So we come to Episodes dubbed in Italian. In this case, Sky Atlantic will need an additional week to air the fully localized episode. This means that if, for example, the first episode with subtitles airs on January 16th, the same episode will arrive on January 23rd complete with dubbing – exactly a week later.
Usually – and this is also confirmed by the official Sky TV Guide – this is the case fully localized episodes will air the following Monday in prime time to the original US broadcast. For example, the first dubbed episode will be broadcast on January 23 at 9:15 p.m. Italian time.
Below are therefore the dates of the nine episodes and their release in Italian:
episode 1: January 23, 9:15 p.m
episode 3: February 6, 9:15 p.m
Episode 4: February 13, 9:15 p.m
episode 7: March 6, 9:15 p.m
episode 8: March 13, 9:15 p.m
We hope this has helped our readers clarify the release of The Last of Us episodes in Italian – which will also feature Lorenzo Scattorin, Joel's voice in video games.


text:
Girl Forced Into Blood Transfusion Can't Sue
Court House News
Jeff D. Gorman
(CN) - It is too late for a 15-year-old Jehovah's Witness to fight the appointment of a guardian who forced her to undergo a life-saving blood transfusion, the Wisconsin Supreme Court ruled.
Sheila W., as she is named in the decision, was 15 when she was diagnosed in early 2012 with aplastic anemia, an illness in which the patient's immune system attacks the bone marrow.
She declined to undergo life-saving blood transfusions, and her parents supported her decision. They are Jehovah's Witnesses and believe that God does not allow blood transfusions.
Citing the biblical passage Acts 15: 28-29, Sheila told a Dane County judge that a transfusion would be equivalent to "rape."
When the county petitioned for temporary physical custody, the court held a hearing at the hospital and appointed a temporary guardian to decide whether to consent to the recommended transfusions.
With the guardian's consent, "an undetermined number of blood transfusions were administered to Sheila," according to the ruling.
Sheila appealed, but the order to appoint the guardian expired while the action was pending and the Court of Appeals dismissed the case as moot.
The Wisconsin Supreme Court affirmed Wednesday.
"No determination of this court will have any practical legal effect upon an existing controversy because the order being appealed has expired," the unsigned opinion states.
While all of the parties agreed on the mootness subject, Sheila wanted the state's highest court to rule on the issue of whether Wisconsin recognizes her rights as a mature minor to make medical decision and whether the appointment of the guardian violated her constitutional rights.
Despite their acknowledgement that the case "undoubtedly presents issues of public importance," the justices declined to rule on the merits of the case.
"We deem it unwise to decide such substantial social policy issues with far-reaching implications based on a single fact situation in a case that is moot," they wrote.
Justice David Prosser wrote a longer concurrent opinion.
"Permitting a minor to refuse lifesaving medical treatment comes uncomfortably close to permitting a minor to commit suicide," he wrote.
Justice Michael Gabelman wrote in dissent that the court should have ruled on the merits of the case.
"The Sheila W.s of this state may have to wait a long time before the legislators on white horses arrive," Gabelman wrote. "In the meantime, the actual problem of what to do with minors who refuse life-saving treatment will remain unresolved."
One week earlier, the court affirmed the convictions of Leilani and Dale Neumann, a "Pentecostal" couple whose daughter died as they prayed over her instead of seeking medical treatment.
Groups/Topics: Jehovah Witnesses, legal


text:
Inside the US Capitol for impeachment: National Guard in every corner
Members of the National Guard deployed in the Capitol Visitors Centre, on Jan 13, 2021.PHOTO: AFP
Jan 14, 2021, 12:50 pm SGT
https://str.sg/JzwB
WASHINGTON (NYTIMES) - They slept on the marble floors, lined up for coffee at the 24-hour snack bar and marvelled at the marble likenesses of the nation's founders in the Rotunda and Statuary Hall.
They snapped photos with their phones, ate pizza and sometimes played cards, their M4 carbines at their sides.
Throngs of armed, camouflage fatigue-clad members of the National Guard ringed the Capitol and lined its halls on Wednesday (Jan 13), weapons, helmets and backpacks stacked in seemingly every corner of the complex.
The heavily militarised presence provided a jarring and sobering backdrop to the House chamber as a majority of lawmakers moved to impeach a sitting American president for inciting an insurrection on the nation's Capitol.
It evoked reminders of the rioters who just one week earlier had stormed the complex as its terrified occupants took shelter inside the barricaded House chamber and secure locations across the Capitol - and the recriminations that remained before President-elect Joe Biden's inauguration.
"It doesn't belong here," Representative Elaine Luria, a Virginia Democrat and veteran who served 20 years in the Navy, said of the military presence in the building.
"It is something that is out of place.
"I hate the idea that we're going to change in a way - be harder, more difficult or more cumbersome for people to come enjoy the historic monument - that this is because of what happened last week," she added.
Much like the lawmakers, aides and reporters who were still exchanging accounts of where they were during the siege of pro-Trump supporters, Capitol Hill on Wednesday appeared to be torn between nursing the open wounds left by deadly riots and the need to lay the groundwork for healing under a new administration.
Capitol workers feverishly worked in recent days to complete preparations for the inauguration on Jan 20 - hanging blue curtains over the entrance to the Rotunda and brushing dust off the statues - among reminders of the violence.
Window panes remained splintered and cracked in parts of the Capitol and two holes were left over the entry to the office of House Speaker Nancy Pelosi of California after rioters stole her embossed wood plaque.
Freshmen lawmakers delivered their maiden floor speeches on the merits of charging President Donald Trump with high crimes and misdemeanours for inciting an insurrection.
After a majority of the House voted to impeach Mr Trump, Ms Pelosi spoke from the same lectern that a pro-Trump supporter had been photographed gleefully hauling across the Capitol.
"I don't have enough adjectives to describe how disgusted I am with what happened and the point that we're at - it's sad, it's disgusting, it's sad," said Representative Brian Mast, a Florida Republican and Army veteran who lost his legs while serving in Afghanistan.
He gave tours of the Rotunda to members of the Guard as a way of showing gratitude for their service. Mr Mast also voted to overturn the results in both Arizona and Pennsylvania, and expressed no regret about those votes. He was not among the 10 Republicans who voted to impeach Mr Trump.
Outgoing US Capitol police chief says House, Senate officials hamstrung his efforts: Media
Experts and lawmakers aghast at US Capitol security failure
Some lawmakers lamented the threat that made the military's presence necessary, with many Democrats irate about the role they said their own Republican colleagues had played in whipping up the rage of the mob that assaulted the Capitol, putting lawmakers' lives in danger.
"It should not and will not be tolerated," Representative Hakeem Jeffries, a New York Democrat, told reporters.
"And that's why extraordinary security measures have been taken."
Members of the National Guard receive food in the Capitol Visitors Centre on Capitol Hill, on Jan 13, 2021. PHOTO: AFP
In response in part to concerns about Republicans bringing guns to the House floor, new magnetometers have been installed outside the doors to the chamber, a security measure that was challenging for several lawmakers.
Typically allowed to bypass the magnetometers at the entrances to the building, several Republicans grumbled about the added layer of security and some made a point of pushing past police officers despite setting off the alarm.
"You're taking valuable resources completely away from where it needs to be without any consultation, and you guys did it without any consultation from the minority," Representative Rodney Davis of Illinois, the top Republican on the House Administration Committee, seethed to Representative Steny Hoyer of Maryland, the House majority leader, on Tuesday.
With multiple people testing positive for the coronavirus after sheltering in a room with maskless Republicans, Democrats also enforced a fine system for refusing to wear a mask on the chamber floor.
The magnetometers and heightened security were a small comfort during the vote to impeach Mr Trump, given that several lawmakers are still shaken and questioning the ability to attend the inauguration safely.
US Capitol police left open path for chaos to take deadly turn
US police reassess security for inauguration and demonstrations after Capitol attack
On Wednesday, Ms Pelosi said that the House would vote this month on a rule change that would enforce a fine system for refusing to adhere to the new security protocols, deducting US$5,000 (S$6,630) and US$10,000 from member pay for the first and second offences.
"What we're dealing with now is combating an insurrection, so I feel like everything is upside down," said Representative Colin Allred, a Texas Democrat, who recalled whipping off his jacket on the House floor and preparing to defend his colleagues against the rioters.
"To see National Guardsmen sleeping in the halls, to have the necessary protection of having metal detectors put up to go onto the House floor - I know the word 'unprecedented' is used a lot, but this is unprecedented. And it's also so sad, just so sad.
"It's intended to be open," Mr Allred added of the Capitol: "It's a museum, it's a place where ordinary Americans should feel like they can come and watch the government work."
But while it houses both artifacts of American history and the holders of the highest offices of American democracy, the Capitol complex is, in ordinary times, an accessible fortress.
But with tourists barred as a way to stop the spread of the coronavirus, the presence of hundreds of armed soldiers was even more disconcerting after months of near-empty hallways.
National Guard members sleep, before Democrats begin debating one article of impeachment against US President Donald Trump, on Jan 13, 2021. PHOTO: REUTERS
Several of the soldiers craning their necks to look at the paintings and sculptures etched into the ceiling of the Rotunda said they had never been to the Capitol, even as tourists.
Their colleagues in another room could be seen dozing next to a plaque commemorating the Union troops who were quartered in the Capitol in 1861, in Statuary Hall, and a small group of soldiers posed for a photo with the statue of Rosa Parks.


text:
FDA clears device that treats diabetic foot ulcers for market
December 28, 2017 By Danielle Kirsh
[Image from Sanuwave]
The FDA announced today that it has cleared the Dermapace System diabetic foot ulcer treatment device for market.
Dermapace System is the first shockwave device to treat foot ulcers caused by diabetes, according to the device's creator Sanuwave.
"Diabetes is the leading cause of lower limb amputations," Binita Ashar, director of the division of surgical devices in FDA's Center for Devices and Radiological Health, said in a press release. "The FDA is dedicated to making technologies available that can help improve the quality of life for those with chronic diseases. Additional options for successfully treating and healing ulcer wounds may help prevent lower limb amputations."
About 30.3 million Americans were known to have been diagnosed with diabetes in 2015, according to the American Diabetes Association. Blood vessels and nerves in the feet get damaged from diabetes and can cause infections. According to the FDA, 25% of people who have diabetes will also experience a foot ulcer in their lifetime. If gone untreated, a foot amputation may be needed.
The Dermapace System is designed to treat chronic full-thickness diabetic foot ulcers with wound areas that are smaller than 16 sq. cm, or smaller than the size of the top of a soda can. The foot ulcers extend through the epidermis, dermis, tendon or capsule. The Dermapace System is uses an external shockwave system to stimulate the wound. Pulses of energy like soundwaves help stimulate ulcers in patients 22 years and older with ulcers that have lasted more than 30 days.
In a clinical study, 336 diabetic patients who were receiving the usual diabetic ulcer care were given the Dermapace System as well or a placebo shockwave therapy. Patients who had between one and seven treatments using the Dermapace System had increased wound healing at 24 weeks and a 44% wound closure rate. Patients who received the placebo shockwave therapy had a 30% wound closure rate in the same 24-week time period.
Danielle Kirsh
Danielle Kirsh is an award-winning journalist and senior editor for Medical Design & Outsourcing, MassDevice, and Medical Tubing + Extrusion, and the founder of Women in Medtech and lead editor for Big 100. She received her bachelor's degree in broadcast journalism and mass communication from Norfolk State University and is pursuing her master's in global strategic communications at the University of Florida. You can connect with her on Twitter and LinkedIn, or email her at dkirsh@wtwhmedia.com.
BMP Medical plans expansion for Massachusetts facility
What to expect in diabetes care in 2023
How the Philips recall is raising scrutiny of at-home medical devices


With a TV commercial highlighting vacation rentals having aired in Sunday's big game, football fans are discovering why renting vacation homes, condos, villas and cabins is a favorite choice for many versus hotels. Beyond the experiences families and friends build by staying in a home away from home in Ocean Isle Beach or Sunset Beach, NC, there are numerous benefits to choosing vacation rentals – sometimes in ways they'd least expect!
Live music every Friday night in the park Memorial Day through Labor Day at the Ocean Isle Beach park. Pack your picnic and bring your lounge chairs and sit under the ocean breezes as you listen to live music ranging from rock n roll, beach music, big band and more. It's a tradition that many families have grown to love!
Just 15 minute drive from Ocean Isle Beach, is Little River, South Carolina, where you can find the Blue Crab Festival. It is one of the largest festivals in the southeast. Prior to the actual festival on May 15 – 16, much additional festival publicity and excitement will be generated through the following ancillary events: Festival Queen Pageant, 5K Run, Motorcycle Poker Run and Golf Cart Raffle, and other events still under development.
During certain seasons, vacation rental packages can provide even more value, some with 4-bedrooms starting at just $800 per week, plus 1 to 9 bedroom homes and condos. Visit our vacation rentals pages to become familiar with various vacation rental types, reservation rates as well as travel specials available in Ocean Isle Beach and Sunset Beach, NC. You can see the Ocean Isle Beach rentals HERE and our Sunset Beach rentals HERE.
Most Ocean Isle Beach and Sunset Beach vacation rentals come equipped with washers and dryers, and Sloane Realty Vacations also provides free starter kit of toilet paper, paper towels, dish soap and some properties even offer complete linen service. Travelers may choose to use these perks to pack less clothing and toiletries, avoiding commercial airlines' baggage fees and restrictions.
Ocean Isle Beach and Sunset Beach vacation homes and condos can be from 900 to more than 3500 sq. ft., often costing less than a single hotel room by sleeping up to 29 guests versus just a few.
Be sure to visit our Sunset Beach and Ocean Isle Beach Condo Rental listings!
With full kitchens, and sometimes, outdoor grills, Ocean Isle Beach and Sunset Beach vacation rental travelers often make and store meals and snacks for less, including football favorites like homemade nachos during postseason trips. Use local ingredients and recipes for more memorable mealtimes, like fresh mahi, grouper, flounder, trout, shrimp plus more caught just off the shores of Ocean Isle Beach and Sunset Beach. This also provides healthy travel options, cutting the amount of calories typically consumed while on vacation.
When looking into any vacation rental accommodations, check to see if there is an accessible customer service number for emergency needs 24 hours a day, seven days a week, and for after-hour requests. You can some of our basic Rental Policies here.
Most of Sloane Realty Vacation's vacation homes, villa rentals and condos include amenities not found in hotels, some with private swimming pools, whirlpool spas, fireplaces, DVD players, Internet access, game consoles and multiple living rooms. All are also in communities with access to parks and the beach.
Beyond the ability to live like a local in Ocean Isle Beach or Sunset Beach, vacation rental guests can also take advantage of our relationships with activity providers, shops, restaurants, tour companies and more. Sloane Realty Vacations' offers tee time bookings and Golf packages to fit your needs and we also offer coupon books to area restaurants and amusements. Guests can also opt for concierge-type services, including grocery delivery, catered meals, in-home massages and spa treatments to name a few.
Be sure to see Ocean Isle Beach Area Guide and our Things to do in Sunset Beach to help make some amazing plans!
Whether it's for football championships or national Bowl games, concerts, baseball series', basketball or other events, vacation rentals can save fans from the hassle of finding multiple hotel rooms during big events, and on the cost of multiple reservations.
Check out just some of the amazing events in the area.
Other relationships to remember are those made between vacation rental managers and transportation providers, whether it's rental cars, shuttle services, golf carts, bicycles or more. For example, Sloane Realty Vacations can provide assistance with airport transports or rental car recommendations.
Be sure to also visit http://www.brunswickcountychamber.org/events/, which lists more ongoing events in the area.
For general answers to frequently asked questions about vacation rentals or for more information, visit http://www.DiscoverVacationHomes.com as an official category resource.
Also connect with travelers and experts in the Facebook vacation rental community at http://www.facebook.com/DiscoverVacationHomes, and join the conversation on Twitter @GoVacationHomes.


text:
Under threat of victory
opinions/
Since the criminal-oligarchic revolution (or maidan-2, "Dignity revolution") in Ukraine, it has been exactly three years. During this time the country and its army has changed a lot. The status of the armed forces of Ukraine in 2014 is well-known ("Mesh square"). Since then, changes from the point of view of the organizational structure of the armed forces and amount of military equipment is small and insignificant, because for two years, as fighting in the Donbass moved into a slow stage with relatively small losses. Recent tension at avdeevka this situation does not fundamentally change. The beginning of the civil war, the armed forces of Ukraine was completely ruined by the efforts of all four ukrainian presidents (although the only one to blame was, of course, declared yanukovych).
A miracle can be considered the fact that she was able somehow to fight. The reasons for this miracle was a significant upsurge of patriotism that occurred in 2014, and the main thing – that the ukrainian army was soviet, is able to act in any situation and regardless of how mocks her own political power. However, to win, this is not enough. For three years, apu has gained considerable and valuable experience of the ground contact of the war with a serious enemy. This experience, perhaps, can only be considered truly useful to the ukrainian army.
The losses are much more. In particular, the same patriotic enthusiasm almost completely eroded as of the army and of society as a whole. The apu is still very bad with weapons and equipment. Saves all the same soviet legacy. It was so giant that even mass disposal, sale abroad, and now the huge losses in the war was not destroyed, though reduced to three or four times.
However, what is left to fight for a long time. On the other hand, a resource that is finite. Ironically, now, after three years of war in combat units apu operational equipment much more than before. But overall on the balance of it was, of course, is much less. First, because of the very large losses, and second, surprisingly, as a consequence of continued, although on a much smaller scale, exports, and thirdly, due to the complete dismantling of parts machines that were in storage, to restore and repair other damaged in battle.
That is very much reduced it stocks they already tend to zero. Almost no compensation no. It is the restoration of soviet technology, the only way to replenish combat units and even forming new ones. To produce a ame of zero is still formally a very powerful ukrainian defense industry is virtually incapable. Although over the past three years, the defence budget of Ukraine and increased significantly compared with pre-war, providing the army with modern equipment has not become better.
The money is either stolen (largely under it's military budget and written), or, at best, for the apu case is being wasted (under decumulation, in particular, refers to the repair and restoration of soviet technology instead of producing new). Ukrainian officials almost daily reports about the creation of another sample, far superior to their Russian counterparts, but now it's not even funny. Most mass do new product is a 120-mm mortar "Hammer". Released about 200 units, due to the extreme simplicity of this class of weapons. While there have been several cases of mine explosions, in the trunks "Molotov" with the death of the calculations.
The production technology is more complex than samoupravlenia mortar, proved too much for the ukrainian military-industrial complex. In particular, in the summer of 2014 in lviv armored plant has promised to expand production of armored vehicle "Dozor-b" in the amount of 100 units per year. This car is very unpretentious, these really can and should be churning out by the hundreds. In reality, is made of 10 units, which barely managed to shove into the army (she wanted to make "Patrols" because of the very low quality).
This is where it ended. The plant now has no money, no cars. Very strange situation with the btr-4. How many of them entered the army for three years of war, are difficult to understand.
It is not excluded that it was limited to those 42 instances, which in 2014, Iraq refused due to cracks in buildings. For their cars, not staged baghdad, amiss. Could the ukrainian defense industry to produce new btr-4 is specifically for the apu, remains unclear. Apparently, if failed, then only a few units, although such machines also need to produce hundreds.
Tanks "Oplot" for the apu kharkov plant in 2014 promised in the first year 40, and then 120. Still not made a single, almost got up and executes a single contract for the export of these tanks (for thailand that is already frantically looking for a replacement). To make combat aircraft and helicopters of the ukrainian defense industry could not never. Unclear situation with ammunition, which are consumed in large quantities. It is unknown how many, how much spent and how much is produced (if possible).
Plus the resource of Eastern Europe. It can also be used. In spite of all the talk so far there has been no supply to Ukraine, heavy equipment from former Warsaw pact countries, now members of NATO. But objectively speaking, she does not need Ukraine.
Yet she has such technology more and of better quality than Eastern European countries. But the supply of any weapons from there to Ukraine is quite likely, especially since its completely impossible to capture. However, some types of munitions in Eastern Europe, just not (for example rockets for mlrs "Uragan" and "Smerch"). Thus, to rely on its military-industrial complex of the ukrainian army is not necessary. The supply of soviet equipment from Eastern Europe, again, possible, but so far none of it makes sense.
The more Western weapons 70-80 years. It is no better than the soviet, the ukrainian military have considerable time on its development. With regard to the latest of Western weapons, then give it to Kiev, no one will, and the purchase of a few samples will take the entire military budget of the country. The situation seems stalemate, but in reality it is not. The ruling oligarchic group, making three years ago the coup, did not plan any divorce from crimea or Donbas conflict, but both was a real godsend.
In political terms it is allowed to acquire the highest from the point of view of the West title "Victim of Russian aggression". The main thing is that war has become a great business. Apart from the above navarivanija on a failed defense order, money is made by selling equipment and uniforms for officers and soldiers, to trade with the dnr/lnr through the front line, including weapons and combat equipment (a considerable part of the militia not captured and just bought from the apu). This business embraces the highest state authorities, the defense ministry and defense industry, a considerable part of the officers, and even privates at the front, the volunteer movement.
To abandon that no one wants, especially when catastrophic economic situation in the country. And finally, thanks to the war of the ukrainian oligarchic anarchic democracy turned into a military-oligarchic dictatorship. In this regard, the prediction that Ukraine will repeat the operation "Storm" (in 1995, just a few days the croats eliminated the serbian krajina, and belgrade to come), completely frivolous. Not because Ukraine is not croatia, and Russia – not serbia, but because of the Kiev authorities it is strictly not necessary. Its only goal is the complete and final looting of the country.
If the war is over, by this government just a couple of months there will be serious questions of its own citizens and the West. So not matter the number of produced "Molotov", "Patrols" and "Bulwark" lost t-64, bmp-2 and btr-80. And certainly the number of deaths in endless war citizens, "Made the European choice".
"Winter marsh": myths and reality
American soldiers have defiled themselves. On the official website of the 173rd airborne brigade of the United States there was a comment of the soldier, revealing the true attitude of the "Democrats" to the people of the Republic...
The Munich security conference. The globalization of everything
Held a regular meeting at the level of senior government officials of different countries in the framework of the annual conference in Munich, Germany.According to the results of the performances of the representatives of Europe a...
NATO soldiers are not to blame
The Director of the Department of information of Estonia Mikk Marran expressed concern that the possibility of fights with the participation arrived in the country the British military can be provoked by Moscow. This was reported ...