text:
package FBS::Load;

use 5.01;
use warnings;
use strict;
use Carp;
use Smart::Comments;
use POSIX;
use Test::More;

our ( @ISA, $VERSION, @EXPORT_OK );

BEGIN {
    $VERSION = '0.0.1';

    require Exporter;
    @ISA = qw(Exporter);
    @EXPORT_OK =
      qw(get_user_param get_connect get_cobdate_sql welcome_cob_date test_10_persent);

}

#use version;
#my $VERSION = qv('0.0.1');
# Other recommended modules (uncomment to use):
#use IO::Prompt;
#use Perl6::Export;
#use Perl6::Slurp;
#use Perl6::Say;
#use YAML::Tiny;
use YAML::Tiny;

#read config

sub get_user_param {
    my ( $pwd, $config_name ) = @_;

    my $my_yml_file = $pwd . qq{/$config_name};

    # Open the config
    my $yaml = YAML::Tiny::LoadFile($my_yml_file);
    return $yaml;
}

#conn to database
sub get_connect_string {
    my $yaml              = shift;
    my $init_user         = shift;
    my $user              = $yaml->{ $init_user . '_un' };
    my $password          = $yaml->{ $init_user . '_pw' };
    my $prod_database_tns = $yaml->{prod_database_tns};
    my $driver            = $yaml->{driver};

 #return " sqlsh -d DBI:$driver:$prod_database_tns -u $user -p $password -i < ";
    my $connections;
    my $MAX_TRIES = 3;
  TRY:
    for my $try ( 1 .. $MAX_TRIES )
    {    ### Connecting to server $prod_database_tns under user $user... done
        $connections =
          DBI->connect( 'dbi:' . $driver . ':' . $prod_database_tns,
            $user, $password );
        last TRY if $connections;
    }
    croak "Can't contact server ($prod_database_tns)"
      if not $connections;
    return $connections;
}

#
# make connect to database
#
sub get_connect {
    my $ref_init_users = shift;
    my $yaml           = shift;
    my @init_users     = @{$ref_init_users};
    my %connect_of;
    for my $user (@init_users) {
        $connect_of{$user} = get_connect_string( $yaml, $user );
    }
    return \%connect_of;
}

#
# get sql for search COB_DATE
#
sub get_cobdate_sql {
    return <<END;
select to_char(t.cob_date, 'yyyy-mm-dd') cd,
       to_char(t.cob_date, 'dd-Mon-yyyy') cd_disp,
       case
         when t.is_tue_cob = 1 then
          'WE'
         when t.is_me_cob = 1 then
          'ME'
         else
          'WE'
       end we_name
  from fbs_owner.FBS_COB_DATES t
 where cob_date <= sysdate -- + 6
   and rownum < 2
 order by t.cob_date desc
END
}

#
# get sql for search COB_DATE
#
sub welcome_cob_date {
    my ( $rwa_owner_user, $ref_ini ) = @_;
    my ( $ref_connect,    $ref_cd )  = @{$ref_ini};
    my %connect_of = %{$ref_connect};
    my ( $cob_date, $cob_date_display, $we_name ) = @{$ref_cd};
    my $now_time = get_now( $rwa_owner_user, $ref_connect, $cob_date );
    my $BST =
      "London time:\t" . DateTime->now->set_time_zone("Europe/London")->iso8601;
    my $disp = qq{
For COB_DATE=$cob_date
1 http://jira.gto.intranet.db.com:2020/jira/secure/Dashboard.jspa
2 Create Issue ('c')
Project : FRM Disclosures Support;
Issue Type: Production support;
Create -> sybmit
Priority->Medium;Component/s->FBS
Title ->$we_name FBS load $cob_date_display
==========================================================
Description
==========================================================
For $we_name FBS load it needs to:

    * do regular FBS data load (fcl_copy_tuned_new_prod.sh
      for FCL_COPY, EUS script)
    * check manually FxRates table load
    * check manually DB_INSTRUMENT tables load
    * prepare checking counts report

Component/s: FBS
Assignee: "Assign To Me"
Priority: Medium (don't change)
==========================================================
add Watchers (nicks for speed)
==========================================================
eealina,marlch,herrdx,agrahar,bhnehas
==========================================================
NOW_TIME: $now_time
BST_TIME: $BST
==========================================================
add number of Jira to "runs history" in
https://wiki.tools.intranet.db.com/confluence/display/FCL/FBS+Production+Life+Cycle
};
    return $disp;
}

#
# data in t+1 10pm fiormat, where t=COB_DATE
#
sub get_now {
    my ( $rwa_owner_user, $ref_connect, $cob_date ) = @_;
    my %connect_of = %{$ref_connect};
    my $sql        = q{};
    $sql = <<"END";
select 't+'||round(trunc(sysdate)- to_date('$cob_date','yyyy-mm-dd'))||' '||to_char(sysdate,'hham') "Time Now" from dual
END

    my $dbh = $connect_of{$rwa_owner_user};
    my $now = $dbh->selectrow_array($sql);
    return $now;

#select 't+'||round(sysdate- to_date('$cob_date','yyyy-mm-dd'))||' '||to_char(sysdate,'hhmiam') "Time Now" from dual

}

#test if bigger or lower not lower then 10%
sub test_10_persent {
    my ( $calc_value, $orig_value, $persent, $message ) = @_;

    if ( $calc_value >= $orig_value ) {
        cmp_ok( $calc_value, '>=', $orig_value,
            $message . " $calc_value >= $orig_value " );
    }
    else {
        my $cal_persent =
          floor( abs( ( ( $calc_value - $orig_value ) / $orig_value ) * 100 ) );
        cmp_ok( $cal_persent, '<=', $persent,
            $message . " $calc_value <= $orig_value but not lower then 10 %" );
    }
}

# Module implementation here

1;    # Magic true value required at end of module
__END__

=head1 NAME

FBS::Load - [Weekly load FBS data in group SL3 . Automate some operation and stored rules in local database. SQL::Lite]

=head1 VERSION

This document describes FBS::Load version 0.0.1

=head1 SYNOPSIS

    use FBS::Load;

=for author to fill in:
    Brief code example(s) here showing commonest usage(s).
    This section will be as far as many users bother reading
    so make it as educational and exeplary as possible.

=head1 DESCRIPTION

=for author to fill in:
    Write a full description of the module and its features here.
    Use subsections (=head2, =head3) as appropriate.

=head1 INTERFACE

=for author to fill in:
    Write a separate section listing the public components of the modules
    interface. These normally consist of either subroutines that may be
    exported, or methods that may be called on objects belonging to the
    classes provided by the module.

=head2 Methods

=over 4

=item *  C<< get_user_param ( $pwd, $config_name  ) >>

=item *  my $yaml =  get_user_param( $ENV{PWD}, 'fbs_load.yml' );    #Global hash with parameters

Read ini file_name as input parameter in YAML in current directory.Returns hash $yaml.

=item *  C<< get_connect_string (   $yaml, $init_user ) >>

=item *  $connect_of{$user} = get_connect_string( $yaml, $user );

Read connect parameters from $yaml hash, make connect string and make connect to database:

=item *  C<< get_connect ( \@init_user_connects, $yaml  ) >>

=item *  my %connect_of  = ();my $ref_connect = \%connect_of;
=item *  my $ref_connect = get_connect( \@init_user_connects, $yaml ); %connect_of  = %{$ref_connect};

Make connect to appropriate database

=item *  C<< get_cobdate_sql ( ) >>

=item *  my $ref_cd = $dbh_fbs->selectrow_arrayref( get_cobdate_sql() );

Return sql for find COB_DATE from fbs_owner.FBS_COB_DATES

=item *  C<< welcome_cob_date ( $rwa_owner_user, $ref_ini  ) >>

=item *  my $echo_curr_fbsl_load = welcome_cob_date($rwa_owner_user, $ref_ini);
=item *  print $echo_curr_fbsl_load;

Return current FBS load parameters for create Jira and information needed to add to Confluence.

=item *  C<< get_now ( $rwa_owner_user, $ref_connect, $ref_cd ) >>

=item *  my $now_time = get_now($rwa_owner_user, $ref_connect,$cob_date);

Return date in format  t+1 10pm where t - COB_DATE.

=item *  C<< test_10_persent( $calc_value, $orig_value, $persent, $message ) >>

=item *  test is passed if the result is more or less does not less than 10 per cent

use Test::More qw/no_plan/;
use POSIX;
my $calc_value = 22;
my $orig_value = 20;
my $persent    = 10;      #%
my $message    = 'MIS';

test_10_persent( $calc_value, $orig_value, $persent, $message );

=back

=head1 DIAGNOSTICS

=for author to fill in:
    List every single error and warning message that the module can
    generate (even the ones that will "never happen"), with a full
    explanation of each problem, one or more likely causes, and any
    suggested remedies.

=over

=item C<< Error message here, perhaps with %s placeholders >>

[Description of error here]

=item C<< Another error message here >>

[Description of error here]

[Et cetera, et cetera]

=back

=head1 CONFIGURATION AND ENVIRONMENT

=for author to fill in:
    A full explanation of any configuration system(s) used by the
    module, including the names and locations of any configuration
    files, and the meaning of any environment variables or properties
    that can be set. These descriptions must also include details of any
    configuration language used.

FBS::Load requires no configuration files or environment variables.

=head1 DEPENDENCIES

=for author to fill in:
    A list of all the other modules that this module relies upon,
    including any restrictions on versions, and an indication whether
    the module is part of the standard Perl distribution, part of the
    module's distribution, or must be installed separately. ]

None.

=head1 INCOMPATIBILITIES

=for author to fill in:
    A list of any modules that this module cannot be used in conjunction
    with. This may be due to name conflicts in the interface, or
    competition for system or program resources, or due to internal
    limitations of Perl (for example, many modules that use source code
    filters are mutually incompatible).

None reported.

=head1 BUGS AND LIMITATIONS

=for author to fill in:
    A list of known problems with the module, together with some
    indication Whether they are likely to be fixed in an upcoming
    release. Also a list of restrictions on the features the module
    does provide: data types that cannot be handled, performance issues
    and the circumstances in which they may arise, practical
    limitations on the size of data sets, special cases that are not
    (yet) handled, etc.

No bugs have been reported.

Please report any bugs or feature requests to
C<bug-fbs-load@rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org>.

=head1 AUTHOR

Nikolay Mishin  C<< <mi@ya.ru> >>

=head1 LICENCE AND COPYRIGHT

Copyright (c) 2011, Nikolay Mishin C<< <mi@ya.ru> >>. All rights reserved.

This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself. See L<perlartistic>.

=head1 DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.


text:
require 'csv'
require 'MrMurano/ReCommander'
require 'MrMurano/Solution-ServiceConfig'

module MrMurano
  class Timeseries < ServiceConfig
    def initialize(api_id=nil)
      # FIXME/2017-07-03: What soln types have timeseries?
      @solntype = 'application.id'
      super
      @service_name = 'timeseries'
    end

    def query(query)
      call(:query, :post, q: query)
    end

    def write(writestr)
      call(:write, :post, query: writestr)
    end

    def command(cmd)
      call(:command, :post, q: cmd)
    end
  end
end

command :timeseries do |c|
  c.syntax = %(murano timeseries)
  c.summary = %(About Timeseries)
  c.description = %(
These commands are deprecated.

The timeseries sub-commands let you interact directly with the Timeseries
instance in a solution. This allows for easier debugging, being able to
quickly try out different queries or write test data.
  ).strip
  c.subcmdgrouphelp = true

  c.action do |_args, _options|
    ::Commander::UI.enable_paging unless $cfg['tool.no-page']
    say MrMurano::SubCmdGroupHelp.new(c).get_help
  end
end

command 'timeseries query' do |c|
  c.syntax = %(murano timeseries query <query string>)
  c.summary = %(Query the timeseries database)
  c.description = %(
This command is deprecated.

Query the timeseries database.
  ).strip
  c.option '-o', '--output FILE', %(Download to file instead of STDOUT)
  c.option '--[no-]json', %(Display results as raw json)
  c.option '--[no-]csv', %(Display results as CSV)

  c.action do |args, options|
    # SKIP: c.verify_arg_count!(args)
    options.defalts json: false, csv: false
    sol = MrMurano::Timeseries.new
    ret = sol.query args.join(' ')

    $cfg['tool.outformat'] = 'json' if options.json
    $cfg['tool.outformat'] = 'best csv' if options.csv

    io = File.open(options.output, 'w') if options.output
    sol.outf(ret, io) do |_dd, ios|
      (ret[:results] || []).each do |res|
        (res[:series] || []).each do |ser|
          sol.tabularize(
            {
              title: ser[:name],
              headers: ser[:columns],
              rows: ser[:values],
            },
            ios
          )
        end
      end
    end
    io.close unless io.nil?
  end
end
alias_command 'tsq', 'timeseries query'

command 'timeseries write' do |c|
  c.syntax = %(murano timeseries <write string>)
  c.summary = %(Write data into the timeseries database)
  c.description = %(
This command is deprecated.

Write data into the timeseries database.
  ).strip
  c.option '--[no-]json', %(Display results as raw json)
  c.action do |args, options|
    c.verify_arg_count!(args)
    options.defalts(json: false)
    $cfg['tool.outformat'] = 'json' if options.json
    sol = MrMurano::Timeseries.new
    ret = sol.write args.join(' ')
    sol.outf ret
  end
end
alias_command 'tsw', 'timeseries write'

command 'timeseries command' do |c|
  c.syntax = %(murano timeseries command <db command>)
  c.summary = %(Execute a non-query command in the database)
  c.description = %(
This command is deprecated.

Execute a non-query command in the database.
  ).strip
  c.option '--[no-]json', %(Display results as raw json)
  c.action do |args, options|
    # SKIP: c.verify_arg_count!(args)
    options.defalts(json: false)
    $cfg['tool.outformat'] = 'json' if options.json
    sol = MrMurano::Timeseries.new
    ret = sol.command args.join(' ')
    sol.outf ret
  end
end

redpajama_set_name: RedPajamaGithub


text:
    $navpath

$generatedby  $doxygenversion

<address class="footer">
$generatedby  $doxygenversion

  Privacy |
  Site terms |
  Cookie preferences

</address>


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Raft Tutorial</title>

<meta name="keywords" content="Raft, Language, Stream, Parallel, Streaming,
                               Threads, Process, Compiler" />
<meta name="description" content="Short tutorial and introduction
                                  to the Raft language and run-time" />

Raft Tutorial

Class Declaration

       A class is the basic unit within Raft.  A class can have several visibility levels, the default being
       private if no visibility is specified.  Visibility is modified with the keywords @public,
       @private,@protected.  Public visibility means that the members specified
       after the keyword are visible to any calling class.  Protected visibility means that any class
       extending this class can use the methods or variables within this scope.  Private visibility ensures
       that the code after this keyword is usable only by this class or accessed through accessor methods.

1 class Example{
2 @public:
3
4 @protected:
5
6 @private:
7 }

Inheritance

      Classes can extend one class in order to inherit functionality, or implement an interface along with
      extending another class.  Single inheritance greatly simplifies virtual function lookup.

1 class Example : extends Kernel{
2
3 }

 Generics

      Raft also supports generic classes where some types or class variables are left as variables until
      compile time where they must be specified.  The example below shows a generic class Example
      which takes a class Type and specifies a constant array array which has both its
      elements with the default initialization of 2 for both.  Generic arguments with default parameters
      are not required to be specified if the user wants to keep the default values.

1 class Example<class Type, int32 array[2](2)> : extends Kernel{
2
3 }

Types

   Raft supports the following types:

   int8 - signed 8-bit integer

   char - char, size of int8

   int16 - signed 16-bit integer

   int32 - signed 32-bit integer

   int64 - signed 64-bit integer

   uint8 - un-signed 8-bit integer

   uint16 - un-signed 16-bit integer

   uint32 - un-signed 32-bit integer

   uint64 - un-signed 64-bit integer

   float32 - 32-bit floating point

   float64 - 64-bit floating point

   float96 - 96-bit floating point

   String - String object, arbitrary length

Streaming

   Raft explicitly supports stream processing.  It diverges from styles
   that have been used in the past in order to more naturally express a
   streaming application in conjunction with more traditional procedural
   and threaded code.  The keyword streams is used to specify a
   function or constructor (yikes!!) that utilizes the streaming paradigm.
   The following example has a single constructor with the streams keyword.
   This means the entire class is built to support a single streaming kernel.

 1 class Sum<class Type, int32 array[2](2)> : extends Kernel{
 2    streams [[ int32 a ]] Sum[[ int32 x0, int32 x1 ]]
 3    {
 4       /**
 5        * With no further direction the compiler infers that you
 6        * want a pair-wise addition of all elements available on
 7        * input streams x0 and x1 and assign the sum to the outbound
 8        * stream a.
 9        */
10       a = x0 + x1;
11    }
12 }

   For more complicated behavior there is another way of specifying the
   behavior of a section of code with respect to streams as is shown in
   the next example.

 1 class Sum<class Type, int32 array[2](2)> : extends Kernel{
 2    streams [[ int32 a ]] Sum[[ int32 x0, int32 x1 ]]
 3    {
 4       /**
 5        * using the get method of the base class Kernel, a user
 6        * tells the compiler explicitly to remove the number of
 7        * items specified in the parameter, e.g. x0.get( 1 ) would
 8        * specify 1 item to be removed.  The push function has the
 9        * effect on an output stream of sending the specified number of
10        * items, e.g. a.push( #elements, elements ) sends #elements items.
11        * Send can be modified by adding a third parameter of false to
12        * specify non-blocking behavior.
13        */
14        a.push( 1, x0.get( 1 ) + x1.get( 1 ) );
15    }
16 }

   If initialization variables are needed for a specific kernel, then a standard
   constructor can be used along with a streaming style constructor.  Through
   two different mechanisms.  The first and simplest is to call the non-streaming
   constructor, assigning the instantiated object to a name.  The name can then
   be used with the CreateInstance() function in order to create
   a new instance of this object that has the same configuration parameters
   initialized.  A second method is to use partial evaluation (described in the
   next section).  Partial evaluation provides a way to give parameters to a
   function, in this case a constructor, that can be used in follow on calls
   of that function.

   TODO cut and paste example

Partial Evaluation

   Often it is necessary to produce a method, constructor (as well as the
   streaming counterparts) with some value.  Raft provides a way to provide
   input to a function and provide placeholder values for the rest to
   produce a partially evaluated function.

1 Raft.Function X( test( # , 100 ) );

Or equivalently, the auto keyword will take on the return type of the partial
evaluation operator:

1 auto X( test( # , 100 ) );

Mathematical Operators

Raft supports almost all of the C style operators, specifically:

Iterations

Raft supports many iterations schemes.  The while( condition ){  } and for( initialization ; conditional ; iteration ){  }
loops were exactly as expected.  Future support will include for(variable name : object) style loops which are a bit more convenient
for some operations than the traditional for structure.

Raft also supports a more functional style map operator with the basic syntax of:  function( parameterlist ) /@ data .

1 int32 test_array[]( new int32[100] /* dynamic allocation */,
2                     0 /* initialization */ );
3
4 int32 output_array[]( foo( $ ) @/ test_array );

Where the function foo is defined as:

Threading Support

There is a bit more to the streams keyword that originally specified.  It too can be modified by the carrot operator
in order to specify if this kernel should be run in a separate process or thread.  Additionally a platform can be specified.
These options might be ignored, depending on the optimization level.


text:
package org.ode4j.democpp;

import static org.ode4j.cpp.internal.ApiCppBody.dBodyCreate;
import static org.ode4j.cpp.internal.ApiCppBody.dBodyGetAngularVel;
import static org.ode4j.cpp.internal.ApiCppBody.dBodyGetLinearVel;
import static org.ode4j.cpp.internal.ApiCppBody.dBodyGetQuaternion;
import static org.ode4j.cpp.internal.ApiCppBody.dBodySetAngularVel;
import static org.ode4j.cpp.internal.ApiCppBody.dBodySetLinearVel;
import static org.ode4j.cpp.internal.ApiCppBody.dBodySetQuaternion;
import static org.ode4j.cpp.internal.ApiCppCollision.dCollide;
import static org.ode4j.cpp.internal.ApiCppCollision.dCreateBox;
import static org.ode4j.cpp.internal.ApiCppCollision.dCreatePlane;
import static org.ode4j.cpp.internal.ApiCppCollision.dGeomGetBody;
import static org.ode4j.cpp.internal.ApiCppCollision.dGeomSetBody;
import static org.ode4j.cpp.internal.ApiCppCollision.dSpaceCollide;
import static org.ode4j.cpp.internal.ApiCppCollisionSpace.dSimpleSpaceCreate;
import static org.ode4j.cpp.internal.ApiCppJoint.dJointAttach;
import static org.ode4j.cpp.internal.ApiCppJoint.dJointCreateContact;
import static org.ode4j.cpp.internal.ApiCppJoint.dJointCreatePlane2D;
import static org.ode4j.cpp.internal.ApiCppJoint.dJointSetPlane2DXParam;
import static org.ode4j.cpp.internal.ApiCppJoint.dJointSetPlane2DYParam;
import static org.ode4j.cpp.internal.ApiCppJoint.dParamFMax;
import static org.ode4j.cpp.internal.ApiCppJoint.dParamVel;
import static org.ode4j.cpp.internal.ApiCppOdeInit.dCloseODE;
import static org.ode4j.cpp.internal.ApiCppOdeInit.dInitODE2;
import static org.ode4j.cpp.internal.ApiCppOther.dAreConnected;
import static org.ode4j.cpp.internal.ApiCppWorld.dWorldCreate;
import static org.ode4j.cpp.internal.ApiCppWorld.dWorldSetCFM;
import static org.ode4j.cpp.internal.ApiCppWorld.dWorldSetERP;
import static org.ode4j.drawstuff.DrawStuff.dsDrawBox;
import static org.ode4j.drawstuff.DrawStuff.dsSetColor;
import static org.ode4j.drawstuff.DrawStuff.dsSetTexture;
import static org.ode4j.drawstuff.DrawStuff.dsSetViewpoint;
import static org.ode4j.drawstuff.DrawStuff.dsSimulationLoop;
import static org.ode4j.ode.internal.cpp4j.Cmath.cos;
import static org.ode4j.ode.internal.cpp4j.Cmath.sin;
import static org.ode4j.ode.internal.cpp4j.Cmath.sqrt;
import static org.ode4j.ode.internal.cpp4j.Cstdlib.RAND_MAX;

import org.ode4j.drawstuff.DrawStuff.DS_TEXTURE_NUMBER;
import org.ode4j.drawstuff.DrawStuff.dsFunctions;
import org.ode4j.math.DQuaternion;
import org.ode4j.math.DQuaternionC;
import org.ode4j.math.DVector3;
import org.ode4j.math.DVector3C;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DContactBuffer;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DGeom.DNearCallback;
import org.ode4j.ode.DJoint;
import org.ode4j.ode.DJointGroup;
import org.ode4j.ode.DMass;
import org.ode4j.ode.DPlane2DJoint;
import org.ode4j.ode.DSpace;
import org.ode4j.ode.DWorld;
import org.ode4j.ode.OdeHelper;
import org.ode4j.ode.OdeMath;

/**
 * Test my Plane2D constraint.
 * Uses ode-0.35 collision API.
 *
 */
class DemoPlane2d extends dsFunctions {

	private static final double drand48() {
		//return ((double) rand()) / ((double) RAND_MAX);
		int i1 = OdeMath.dRandInt(RAND_MAX);
		return ((double) i1) / ((double) RAND_MAX);
	}
	//TZ: below is the new version from 0.11.1, but it yields different results
	//in Java and C++
	//#   define drand48()  ((double) (((double) rand()) / ((double) RAND_MAX)))
//	private static final double drand48() {
//		return ((double)rand()) / ((double)RAND_MAX);
//	}

	//
	private static final int N_BODIES = 40;
	private static final float STAGE_SIZE = 8.0f; // in m

	private static final double TIME_STEP = 0.01;
	//private static final double K_SPRING = 10.0;
	//private static final double K_DAMP = 10.0;

	private static DWorld   dyn_world;
	private static DBody[]    dyn_bodies = new DBody[N_BODIES];
	private static DVector3[]    bodies_sides = new DVector3[N_BODIES];

	private static DSpace coll_space_id;
	private static DPlane2DJoint[] plane2d_joint_ids=new DPlane2DJoint[N_BODIES];
	private static DJointGroup coll_contacts;

	private static float[]    xyz = { 0.5f*STAGE_SIZE, 0.5f*STAGE_SIZE, 0.65f*STAGE_SIZE};
	private static float[]    hpr = { 90.0f, -90.0f, 0 };

	private static void     cb_start ()
	/** ********************** */
	{
		//dAllocateODEDataForThread(OdeConstants.dAllocateMaskAll);
		dsSetViewpoint (xyz, hpr);
	}

	private static void     cb_near_collision (Object data, DGeom o1, DGeom o2)
	/********************************************************************/
	{
		DBody     b1 = dGeomGetBody (o1);
		DBody     b2 = dGeomGetBody (o2);
		//dContact    contact = new dContact();
		DContactBuffer contacts = new DContactBuffer(1);

		// exit without doing anything if the two bodies are static
		if (b1 == null && b2 == null) {
			return;
		}

		// exit without doing anything if the two bodies are connected by a joint
		if (b1!=null && b2!=null && dAreConnected(b1, b2))
		{
			/* MTRAP; */
			return;
		}

		contacts.get(0).surface.mode = 0;
		contacts.get(0).surface.mu = 0; // frictionless

		if (dCollide (o1, o2, 1, contacts.getGeomBuffer())!=0);//, sizeof (dContactGeom)))
		{
			DJoint c = dJointCreateContact (dyn_world,
					coll_contacts, contacts.get(0));
			dJointAttach (c, b1, b2);
		}
	}

	private static void     track_to_pos (DBody body, DPlane2DJoint joint_id,
			double target_x, double target_y)
	/************************************************************************/
	{
		double  curr_x = body.getPosition().get0();
		double  curr_y = body.getPosition().get1();

		dJointSetPlane2DXParam (joint_id, dParamVel, 1 * (target_x - curr_x));
		dJointSetPlane2DYParam (joint_id, dParamVel, 1 * (target_y - curr_y));
	}

	private DNearCallback myNearCallBack = new DNearCallback() {
		@Override
		public void call(Object data, DGeom o1, DGeom o2) {
			cb_near_collision(data, o1, o2);
		}
	};

	private static double angle = 0;
	@SuppressWarnings("unused")
	private void cb_sim_step (boolean pause)
	{
		if (! pause)
		{
			//        static double angle = 0;

			angle +=  0.01 ;

			track_to_pos (dyn_bodies[0], plane2d_joint_ids[0],
					( STAGE_SIZE/2 + STAGE_SIZE/2.0 * cos (angle) ),
					( STAGE_SIZE/2 + STAGE_SIZE/2.0 * sin (angle) ));

			/* double   f0 = 0.001; */
			/* for (int b = 0; b < N_BODIES; b ++) */
			/* { */
			/* double   p = 1 + b / (double) N_BODIES; */
			/* double   q = 2 - b / (double) N_BODIES; */
			/* dyn_bodies[b].addForce (f0 * cos (p*angle), f0 * sin (q*angle), 0); */
			/* } */
			/* dyn_bodies[0].addTorque (0, 0, 0.1); */

			final int n = 10;
			for (int i = 0; i < n; i ++)
			{
				//dSpaceCollide (coll_space_id, 0, cb_near_collision);
				dSpaceCollide (coll_space_id, null, myNearCallBack );
				dyn_world.step (TIME_STEP/n);
				coll_contacts.empty ();
			}
		}

		if (true) //# if 1  /* [ */
		{
			// @@@ hack Plane2D constraint error reduction here:
			for (int b = 0; b < N_BODIES; b ++)
			{
				final DVector3C rot = dBodyGetAngularVel (dyn_bodies[b]);
				//final double     []quat_ptr;
				DQuaternionC     quat_ptr;
				DQuaternion           quat= new DQuaternion();
				double                quat_len;

				double q0, q3;
				quat_ptr = dBodyGetQuaternion (dyn_bodies[b]);
				//            quat[0] = quat_ptr[0];
				//            quat[1] = 0;
				//            quat[2] = 0;
				//            quat[3] = quat_ptr[3];
				q0 = quat_ptr.get(0);
				q3 = quat_ptr.get(3);
				quat_len = Math.sqrt (q0 * q0 + q3 * q3);
				q0 /= quat_len;
				q3 /= quat_len;
				quat.set(q0, 0, 0, q3);
				dBodySetQuaternion (dyn_bodies[b], quat);
				dBodySetAngularVel (dyn_bodies[b], 0, 0, rot.get2());
			}
		}//# endif  /* ] */

		if (false)//# if 0  /* [ */
		{
			// @@@ friction
			for (int b = 0; b < N_BODIES; b ++)
			{
				DVector3C vel = dBodyGetLinearVel (dyn_bodies[b]),
				rot = dBodyGetAngularVel (dyn_bodies[b]);
				double       s = 1.00;
				double       t = 0.99;

				dBodySetLinearVel (dyn_bodies[b], s*vel.get0(),s*vel.get1(),s*vel.get2());
				dBodySetAngularVel (dyn_bodies[b],t*rot.get0(),t*rot.get1(),t*rot.get2());
			}
		}//# endif  /* ] */

		{
			// ode  drawstuff

			dsSetTexture (DS_TEXTURE_NUMBER.DS_WOOD);
			for (int b = 0; b < N_BODIES; b ++)
			{
				if (b == 0)
					dsSetColor (1.0f, 0.5f, 1.0f);
				else
					dsSetColor (0f, 0.5f, 1.0f);
				dsDrawBox (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
			}
		}
	}

	/******************/
	public static void main(String[] args)
	{
		new DemoPlane2d().demo(args);
	}

	private void demo(String[] args) {
		int         b;

		dInitODE2(0);

		// dynamic world

		double  cf_mixing;// = 1 / TIME_STEP * K_SPRING + K_DAMP;
		double  err_reduct;// = TIME_STEP * K_SPRING * cf_mixing;
		err_reduct =  0.5 ;
		cf_mixing =  0.001 ;
		//TZ
		dyn_world = dWorldCreate();
		dWorldSetERP (dyn_world, err_reduct);
		dWorldSetCFM (dyn_world, cf_mixing);
		dyn_world.setGravity (0, 0.0, -1.0);

		coll_space_id = dSimpleSpaceCreate (null);
		//coll_space_id = dSweepAndPruneSpaceCreate(null, dSAP_AXES_XYZ);
		//coll_space_id = dHashSpaceCreate(null);

		// dynamic bodies
		for (b = 0; b < N_BODIES; b ++)
		{
			int     l = (int) (1 + sqrt ((double) N_BODIES));
			double  x = (0.5 + (b / l)) / l * STAGE_SIZE;
			double  y = (0.5 + (b % l)) / l * STAGE_SIZE;
			//double  z = REAL( 1.0 ) + REAL( 0.1 ) * (double)drand48();
			double  z = 1.0 + 0.1  * drand48();

			//TZ
//			bodies_sides[b] = new dVector3(
//					(double)( 5. * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) ),
//					(double)( 5. * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) ),
//					z);
			double r2 = drand48();
			double r1 = drand48();
			bodies_sides[b] = new DVector3(
					5. * (0.2 + 0.7*r2) / sqrt((double)N_BODIES),
					5. * (0.2 + 0.7*r1) / sqrt((double)N_BODIES),
					z);

			dyn_bodies[b] = dBodyCreate(dyn_world);
			dyn_bodies[b].setPosition (x, y, z/2);
			dyn_bodies[b].setData (b);//(void*) (size_t)b);
//			dBodySetLinearVel (dyn_bodies[b],
//			(double)( 3. * (drand48 () - 0.5) ),
//			(double)( 3. * (drand48 () - 0.5) ), 0);
			r2 = drand48();
			r1 = drand48();
			dBodySetLinearVel (dyn_bodies[b],
			3. * (r1 - 0.5),
			3. * (r2 - 0.5), 0);

			DMass m = OdeHelper.createMass();
			m.setBox (1, bodies_sides[b].get0(),bodies_sides[b].get1(),bodies_sides[b].get2());
			m.adjust (0.1 * bodies_sides[b].get0() * bodies_sides[b].get1());
			dyn_bodies[b].setMass (m);

			plane2d_joint_ids[b] = dJointCreatePlane2D (dyn_world, null);
			dJointAttach (plane2d_joint_ids[b], dyn_bodies[b], null);
		}
		dJointSetPlane2DXParam (plane2d_joint_ids[0], dParamFMax, 10);
		dJointSetPlane2DYParam (plane2d_joint_ids[0], dParamFMax, 10);

		// collision geoms and joints
		dCreatePlane (coll_space_id,  1, 0, 0, 0);
		dCreatePlane (coll_space_id, -1, 0, 0, -STAGE_SIZE);
		dCreatePlane (coll_space_id,  0,  1, 0, 0);
		dCreatePlane (coll_space_id,  0, -1, 0, -STAGE_SIZE);

		for (b = 0; b < N_BODIES; b ++)
		{
			DGeom coll_box_id;
			coll_box_id = dCreateBox (coll_space_id,
					bodies_sides[b].get0(), bodies_sides[b].get1(), bodies_sides[b].get2());
			dGeomSetBody (coll_box_id, dyn_bodies[b]);
		}

		coll_contacts = OdeHelper.createJointGroup();

		{
			// simulation loop (by drawstuff lib)
			//drawstuff_functions.setVersion(DS_VERSION);
			//		drawstuff_functions.start = &cb_start;
			//		drawstuff_functions.step = &cb_sim_step;
			//		drawstuff_functions.command = 0;
			//		drawstuff_functions.stop = 0;
			//drawstuff_functions.setPathToTextures(DRAWSTUFF_TEXTURE_PATH);

			dsSimulationLoop (args, 352,288,this);
		}

		dCloseODE();
	}

	@Override
	public void command(char cmd) {
		// Nothing
	}

	@Override
	public void start() {
		cb_start();
	}

	@Override
	public void step(boolean pause) {
		cb_sim_step(pause);
	}

	@Override
	public void stop() {
		// Nothing
	}
}