GIFEncoder.Class.php and a no loop GIF animation - animation

I'm using the GIFEncoderclass to convert a series of GIF images to an animated Gif.
What I am trying to do is set the loop so that it doesnt repeat.
When I set loop to 1, in Chrome and IE it doesnt play once... but loops once (so plays twice). In FireFox though it works as intended, plays one doesn't loop.
Is this a bug in the GIFEncoder?
Am i doing something wrong?
And how do i solve this?
my Code
$gif = new GIFEncoder (
$frames, // frames array
$time, // elapsed time array
1, // loops (0 = infinite)
0, // disposal
3, 2, 1,
0,// rgb of transparency
"url" // source type
);
GIFEncoder class
Class GIFEncoder {
var $GIF = "GIF89a"; /* GIF header 6 bytes */
var $VER = "GIFEncoder V3.00"; /* Encoder version */
var $BUF = Array ( );
var $OFS = Array ( );
var $SIG = 0;
var $LOP = 0;
var $DIS = 2;
var $COL = -1;
var $IMG = -1;
var $ERR = Array (
'ERR00'=>"Does not supported function for only one image!",
'ERR01'=>"Source is not a GIF image!",
'ERR02'=>"Unintelligible flag ",
'ERR03'=>"Does not make animation from animated GIF source",
);
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFEncoder...
::
*/
function GIFEncoder (
$GIF_src, $GIF_dly, $GIF_lop, $GIF_dis,
$GIF_red, $GIF_grn, $GIF_blu, $GIF_ofs,
$GIF_mod
) {
if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_dly ) ) {
printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] );
exit ( 0 );
}
if ( is_array ( $GIF_ofs ) && count ( $GIF_ofs ) > 1 ) {
$this->SIG = 1;
$this->OFS = $GIF_ofs;
}
$this->LOP = $GIF_lop === false ? false : (( $GIF_lop > -1 ) ? $GIF_lop : 0);
$this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2;
$this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ?
( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1;
for ( $i = 0; $i < count ( $GIF_src ); $i++ ) {
if ( strToLower ( $GIF_mod ) == "url" ) {
$this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) );
}
else if ( strToLower ( $GIF_mod ) == "bin" ) {
$this->BUF [ ] = $GIF_src [ $i ];
}
else {
printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod );
exit ( 0 );
}
if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) {
printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] );
exit ( 0 );
}
for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) {
switch ( $this->BUF [ $i ] { $j } ) {
case "!":
if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) {
printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) );
exit ( 0 );
}
break;
case ";":
$k = FALSE;
break;
}
}
}
GIFEncoder::GIFAddHeader ( );
for ( $i = 0; $i < count ( $this->BUF ); $i++ ) {
GIFEncoder::GIFAddFrames ( $i, $GIF_dly [ $i ] );
}
GIFEncoder::GIFAddFooter ( );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddHeader...
::
*/
function GIFAddHeader ( ) {
$cmap = 0;
if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) {
$cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) );
$this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 );
$this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap );
if($this->LOP !== false)
{
$this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0";
}
}
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFrames...
::
*/
function GIFAddFrames ( $i, $d ) {
$Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) );
$Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1;
$Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end );
$Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 );
$Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 );
$Global_rgb = substr ( $this->BUF [ 0 ], 13,
3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) );
$Locals_rgb = substr ( $this->BUF [ $i ], 13,
3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) );
$Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) .
chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0";
if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) {
for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) {
if (
ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) &&
ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >> 8 ) & 0xFF ) &&
ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >> 0 ) & 0xFF )
) {
$Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 1 ) .
chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0";
break;
}
}
}
switch ( $Locals_tmp { 0 } ) {
case "!":
$Locals_img = substr ( $Locals_tmp, 8, 10 );
$Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 );
break;
case ",":
$Locals_img = substr ( $Locals_tmp, 0, 10 );
$Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 );
break;
}
if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) {
if ( $Global_len == $Locals_len ) {
if ( GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) {
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp );
}
else {
/*
*
* XY Padding...
*
*/
if ( $this->SIG == 1 ) {
$Locals_img { 1 } = chr ( $this->OFS [ $i ] [ 0 ] & 0xFF );
$Locals_img { 2 } = chr ( ( $$this->OFS [ $i ] [ 0 ] & 0xFF00 ) >> 8 );
$Locals_img { 3 } = chr ( $this->OFS [ $i ] [ 1 ] & 0xFF );
$Locals_img { 4 } = chr ( ( $this->OFS [ $i ] [ 1 ] & 0xFF00 ) >> 8 );
}
$byte = ord ( $Locals_img { 9 } );
$byte |= 0x80;
$byte &= 0xF8;
$byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 );
$Locals_img { 9 } = chr ( $byte );
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp );
}
}
else {
/*
*
* XY Padding...
*
*/
if ( $this->SIG == 1 ) {
$Locals_img { 1 } = chr ( $this->OFS [ $i ] [ 0 ] & 0xFF );
$Locals_img { 2 } = chr ( ( $$this->OFS [ $i ] [ 0 ] & 0xFF00 ) >> 8 );
$Locals_img { 3 } = chr ( $this->OFS [ $i ] [ 1 ] & 0xFF );
$Locals_img { 4 } = chr ( ( $this->OFS [ $i ] [ 1 ] & 0xFF00 ) >> 8 );
}
$byte = ord ( $Locals_img { 9 } );
$byte |= 0x80;
$byte &= 0xF8;
$byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 );
$Locals_img { 9 } = chr ( $byte );
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp );
}
}
else {
$this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp );
}
$this->IMG = 1;
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFAddFooter...
::
*/
function GIFAddFooter ( ) {
$this->GIF .= ";";
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFBlockCompare...
::
*/
function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) {
for ( $i = 0; $i < $Len; $i++ ) {
if (
$GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } ||
$GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } ||
$GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 }
) {
return ( 0 );
}
}
return ( 1 );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GIFWord...
::
*/
function GIFWord ( $int ) {
return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) );
}
/*
:::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: GetAnimation...
::
*/
function GetAnimation ( ) {
return ( $this->GIF );
}
}

Found the solution... Just set the loop to False

This class has mistake. Please replace all '$$this->OFS' to '$this->OFS'
$gif = new GIFEncoder (
// 1. frames
array('1.gif', '2.gif', '3.gif'),
// 2. speed - array for frames or number
//array(500,500,500),
20,
// 3. loops - number or false
0,
// 4. disposal ??? - what is it?
2,
// 5-7. transparent RGB
0,0,0,
// 8. padding array with point(x,y) or 0
array(
array(0,50),
array(0,0)
),
// 9. source 'url' or 'bin'
"url"
);

Related

Getting circular dependency error while creating calculated column

I have a measure in my Sales table :
WW_Anchor_R6Sales :=
VAR R6Sales =
CALCULATE (
[MeasureR6Sales] > 0,
FILTER ( Product, Product[Program] = "WW" && Product[Anchor] = "Y" )
)
RETURN
IF ( ISBLANK ( R6Sales ), 0, R6Sales )
LY_Anchor_R6Sales :=
VAR R6Sales =
CALCULATE (
[MeasureR6Sales] > 0,
FILTER ( Product, Product[Program] = "LY" && Product[Anchor] = "Y" )
)
RETURN
IF ( ISBLANK ( R6Sales ), 0, R6Sales )
MeasureR6Sales :=
VAR salesR6 =
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
Sales,
Sales[InvoiceDate] >= EDATE ( [LastClosedMonth], -5 )
&& Sales[InvoiceDate] <= [LastClosedMonth]
&& Sales[SalesAmount] > 0
)
)
RETURN
IF ( ISBLANK ( salesR6 ), 0, salesR6 )
When I have created a calculated column:
WW_Anchor_R6 := IF ( [WW_Anchor_R6Sales] > 0, "Yes", "No" )
I am able to create, but when I am trying to create another calculated column say:
CalculatedColumn1 := IF ( [LY_Anchor_R6Sales] > 0, "Yes", "No" )
it is giving me an error saying that
Failed to save modifications to the server. Error returned: 'A circular dependency was detected: Sales[Calculated Column 1], Sales[WW_Anchor_R6], Sales[Calculated Column 1].
How to fix this error?

How to limit THREE.TransformControls to have only positive values for scale

Is it possible to for the scale gizmo (THREE.TransformControls) to have only positive values ?
Negative values causes the model to turn inside-out.
I found it: goto TransformControls.js and
replace
var newScaleX = oldScale.x * ( 1 + point.x / oldScale.x );
var newScaleY = oldScale.y * ( 1 + point.y / oldScale.y );
var newScaleZ = oldScale.z * ( 1 + point.z / oldScale.z );
point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
if ( scope.axis === "X" ) scope.object.scale.x = newScaleX;
if ( scope.axis === "Y" ) scope.object.scale.y = newScaleY;
if ( scope.axis === "Z" ) scope.object.scale.z = newScaleZ;
with
var newScaleX = oldScale.x * ( 1 + point.x / oldScale.x );
var newScaleY = oldScale.y * ( 1 + point.y / oldScale.y );
var newScaleZ = oldScale.z * ( 1 + point.z / oldScale.z );
point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
if (newScaleX>0)
if ( scope.axis === "X" ) scope.object.scale.x = newScaleX;
if (newScaleY>0)
if ( scope.axis === "Y" ) scope.object.scale.y = newScaleY;
if (newScaleZ>0)
if ( scope.axis === "Z" ) scope.object.scale.z = newScaleZ;

How to open a Buy when a Buy-order hits a T/P, Sell if a Buy-order hits a S/L; a Sell if Sell-order hits a T/P and open Buy if Sell reaches S/L?

I have tried many things but can't get it to work with the code below.
I've tried variations of the logic of the code below but have failed and am not sure where to implement it:
if ( OrderSelect( OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY ) )
{
if ( OrderType() == OP_BUY )
{
if ( OrderClosePrice() > OrderStopLoss() ) Print( "Hit TP" );
else Print( "Hit SL" );
}
else if ( OrderType() == OP_SELL )
{
if ( OrderClosePrice() < OrderStopLoss() ) Print( "Hit TP" );
else Print( "Hit SL" );
}
}
or
Orderselect...
if ( MathAbs( OrderClosePrice()
- OrderTakeProfit()
) > MathAbs( OrderClosePrice()
- OrderStopLoss()
)
) Print( "StopLoss" );
if ( MathAbs( OrderClosePrice()
- OrderTakeProfit()
) < MathAbs( OrderClosePrice()
- OrderStopLoss()
)
) Print( "TakeProfit" );
The OrderSelect() has been an issue for me, so any help will be greatly appreciated.
Below is the EA I'm trying to add it to, but just knowing how and where to put it will help.
extern int MagicNumber = 10001;
extern double Lots = 0.01;
extern double StopLoss = 1;
extern double TakeProfit = 1;
extern int TrailingStop = 0;
extern int Slippage = 3;
//+------------------------------------------------------------------+
// expert start function
//+------------------------------------------------------------------+
int start() // New-MQL4.56789 #strict uses another constructor: int OnTick(){...}
{
double MyPoint = Point;
if ( Digits == 3
|| Digits == 5
) MyPoint = Point*10;
double TheStopLoss = 0;
double TheTakeProfit = 0;
if ( TotalOrdersCount() == 0 )
{
int result = 0;
if ( ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1 ) < iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 1 ) )
&& ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 0 ) > iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 0 ) )
) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is your open BUY rule
{
result = OrderSend( Symbol(),
OP_BUY,
Lots,
Ask,
Slippage,
0,
0,
"Buy",
MagicNumber,
0,
Blue
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Ask + TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Ask - StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
}
return(0);
}
if ( ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 1 ) > iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 1 ) )
&& ( iMA( NULL, 0, 30, 0, MODE_SMA, PRICE_CLOSE, 0 ) < iMA( NULL, 0, 200, 0, MODE_SMA, PRICE_CLOSE, 0 ) )
) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Here is your open SELL rule
{
result = OrderSend( Symbol(),
OP_SELL,
Lots,
Bid,
Slippage,
0,
0,
"Sell",
MagicNumber,
0,
Red
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Bid + StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
}
return(0);
}
}
for ( int cnt = 0; cnt < OrdersTotal(); cnt++ )
{
OrderSelect( cnt, SELECT_BY_POS, MODE_TRADES );
if ( OrderType() <= OP_SELL
&& OrderSymbol() == Symbol()
&& OrderMagicNumber() == MagicNumber
)
{
if ( OrderType() == OP_BUY )
{
if ( TrailingStop > 0 )
{
if ( Bid - OrderOpenPrice() > MyPoint * TrailingStop )
{
if ( OrderStopLoss() < Bid - MyPoint * TrailingStop )
{
OrderModify( OrderTicket(),
OrderOpenPrice(),
Bid - TrailingStop * MyPoint,
OrderTakeProfit(),
0,
Green
);
return(0);
}
}
}
}
else
{
if ( TrailingStop > 0 )
{
if ( ( OrderOpenPrice() - Ask ) > ( MyPoint * TrailingStop ) )
{
if ( ( OrderStopLoss() > ( Ask + MyPoint * TrailingStop ) )
|| ( OrderStopLoss() == 0 )
)
{
OrderModify( OrderTicket(),
OrderOpenPrice(),
Ask + MyPoint * TrailingStop,
OrderTakeProfit(),
0,
Red
);
return(0);
}
}
}
}
}
}
return(0);
}
int TotalOrdersCount()
{
int result = 0;
for ( int i = 0; i < OrdersTotal(); i++ )
{
OrderSelect( i, SELECT_BY_POS, MODE_TRADES );
if ( OrderMagicNumber() == MagicNumber ) result++;
}
return( result );
}
... open WHEN ... is the key part of the goal
OrderSelect() is not of much help for you to solve the "Open WHEN" puzzle. It just crawls accross a db.POOL of records, that MetaTrader Terminal 4 localhost internal DBMS takes care of, which is slow and very, very inefficient way to handle event the order-management tasks, so try to avoid any arbitrary scans thereof in a production-grade system. Here, you even will not get any cardinal piece of information you need for your task from such devastating db.POOL scans, so let's focus on the goal first.
... WHAT ... is the idea behind the goal?
The EA is a scholastically trivial variation on a slow-200 / fast-30 simple moving average cross.
There I guess you would like to add your additional idea of opening additional trades on condition the underlying SMA-cross-originated trade has reached it's { SL | TP }-termination respectively, right?
For such case, Brokers with a MetaTrader Server 4 typically allow you to place a so called pending order, which instructs a Broker, to maintain a record about your will to enter market, supposing a price reaches a pre-defined level -- ( guess what, these would be the { SL | TP } as you requested in the title -- and such record is waiting ( with some more configurable options ), until a such price movement happens or not, during which such position is waiting in an inactive state, called a pending order ...
For Terms & Conditions, kindly check your Broker's contract and/or ask their Customer Care representative. Some special limitations may apply ( better to know a-priori ).
... WHERE ... to put the code?
Without re-designing the provided code ( some minor errors/inefficiencies there ) the code shall go here:
result = OrderSend( Symbol(),
OP_SELL, // PRIMARY SELL <<<AT-MARKET>>>
Lots,
Bid,
Slippage,
0,
0,
"Sell",
MagicNumber,
0,
Red
);
if ( result > 0 )
{
TheStopLoss = 0;
TheTakeProfit = 0;
if ( TakeProfit > 0 ) TheTakeProfit = Bid - TakeProfit * MyPoint;
if ( StopLoss > 0 ) TheStopLoss = Bid + StopLoss * MyPoint;
OrderSelect( result, SELECT_BY_TICKET );
OrderModify( OrderTicket(),
OrderOpenPrice(),
NormalizeDouble( TheStopLoss, Digits ),
NormalizeDouble( TheTakeProfit, Digits ),
0,
Green
);
// ---------------------------------------------------- HERE ADD
OrderSend( Symbol(),
OP_SELLSTOP, // SELL-STOP PENDING ORDER ON SELL.TP
Lots,
NormalizeDouble( TheTakeProfit
- MarketInfo( _Symbol, MODE_SPREAD ),
Digits
),
Slippage,
0, // SL: T.B.D.
0, // TP: T.B.D.
"Sell on Sell.TP",
sTpMagicNumber, // avoid collisions with other logic
0, // never expires
Red
);
OrderSend( Symbol(),
OP_BUYSTOP, // BUY-STOP PENDING ORDER ON SELL.SL
Lots,
NormalizeDouble( TheStopLoss
- MarketInfo( _Symbol, MODE_SPREAD ),
Digits
),
Slippage,
0, // SL: T.B.D.
0, // TP: T.B.D.
"Buy on Sell.SL",
bSlMagicNumber, // avoid collisions with other logic
0, // never expires
Red
);
}
The spread-adjustment is not absolute, as during instable periods of time, the market is exposed to spurious spread volatilities. Again, Brokers' Terms & Conditions apply here, so be carefull.

Spell Checker : Ternary Search tree

i have made a spell checker code using Ternary search tree. Can anybody tell me how to find the next possible word in TST.
for example if i want to search if i search a word "Manly" in spell checker and the word is not present in TST, so the output it gives like
DO YOU MEAN:
"Man"
"Mango"
.
.means possible near words
I have implemented my own spell checker but instead of a simple ternary trie I am using a ternary dag as Peter Kankowski suggests here. You can look at my blog for some details and how I did it. Its in Greek, but you can get an idea.
Edit:
Ok, you are right.
The basic idea is to use a pre-created list of candidates for a given edit distance ( a value of 2 for me is ok ). To reduce the size of the list one can use wildcard characters.
Such a list, of course, can be constructed in different ways. I prefer for / while loops like this ( e.g. for candidates of two substitutions )
void Substitute2( vector<wchar_t*>& v, const wstring& w )
{
size_t len = w.size();
if ( len < 2 )
return;
size_t p1 = 0, p2 = 1;
while ( p1 < len ) {
p2 = p1 + 1;
while ( p2 < len ) {
wchar_t* chars = new wchar_t[ len + 1 ];
for ( size_t i = 0; i < len; ++i ) {
if ( i != p1 && i != p2 ) {
chars[ i ] = w[ i ];
}
}
chars[ p1 ] = '?';
chars[ p2 ] = '?';
chars[ len ] = '\0';
v.push_back( chars );
p2++;
}
p1++;
}
}
After having prepared the candidates list, a simple search in a ternary dag for each item in the list will give us the suggestions for that misspelled word.
void Search( FileNode* pDict, FileNode* pNode, const wchar_t* Word, wstring Sug, set<wstring>& List )
{
if ( IsNullLink( pNode, pDict ) )
return;
if ( *Word == '?' ) {
Search( pDict, GetLo( pNode, pDict ), Word, Sug, List );
Search( pDict, GetEq( pNode, pDict ), Word + 1, Sug + pNode->Char, List );
Search( pDict, GetHi( pNode, pDict ), Word, Sug, List );
} else {
if ( *Word < pNode->Char ) {
Search( pDict, GetLo( pNode, pDict ), Word, Sug, List );
} else if ( *Word > pNode->Char ) {
Search( pDict, GetHi( pNode, pDict ), Word, Sug, List );
} else {
if ( pNode->Char == '\0' )
{
List.insert( Sug );
}
if ( *Word != '\0' ) {
Search( pDict, GetEq( pNode, pDict ), Word + 1, Sug + pNode->Char, List );
}
}
}
}
Note: The dictionary is a compiled (file based) ternary dag
The search for the word in your TST will terminate at a specific location in the tree. From this point, you can simply go up one level in the tree until you hit a level where there is more than just the child you came from.
On that level, you can simply choose the other possible paths and return those words.

How validate a personal identification number in cakephp

I need to validate a field in my form, this field belongs to the personal identification number of my country, this number has 10 digits
Example: card = 1710034065
2 1 2 1 2 1 2 1 2 (coefficient)
1 7 1 0 0 3 4 0 6 (personal identification number)
2 7 2 0 0 3 8 0 12 = 25 (Multiply each digit of the personal number by the
3 coefficient, if the result > 10 add between digits).
add multiplications
The result of the sum
25/10 = 2, Residue 5, divide 10 - residue 5 = 5 (check digit) ** which equals the last number of identity number**
Now I need is to implement this logic in the framework and I have no idea how,
I have a example code in java to get a better idea of what I need to do.
function check_cedula( form )
{
var cedula = form.cedula.value;
array = cedula.split( "" );
num = array.length;
if ( num == 10 )
{
total = 0;
digito = (array[9]*1);
for( i=0; i < (num-1); i++ )
{
mult = 0;
if ( ( i%2 ) != 0 ) {
total = total + ( array[i] * 1 );
}
else
{
mult = array[i] * 2;
if ( mult > 9 )
total = total + ( mult - 9 );
else
total = total + mult;
}
}
decena = total / 10;
decena = Math.floor( decena );
decena = ( decena + 1 ) * 10;
final = ( decena - total );
if ( ( final == 10 && digito == 0 ) || ( final == digito ) ) {
alert( "La c\xe9dula ES v\xe1lida!!!" );
return true;
}
else
{
alert( "La c\xe9dula NO es v\xe1lida!!!" );
return false;
}
}
else
{
alert("La c\xe9dula no puede tener menos de 10 d\xedgitos");
return false;
}
}
Let's say your model name is User and the field in the database is card, you would do the following;
<?php
class User extends AppModel {
/**
* Validation rules
*/
public $validate = array(
'card' => array(
'validateCard' => array(
'rule' => array('validateCard'),
'message' => 'Card does not validate'
)
)
);
/**
* Custom validation rule
* #return bool
*/
public function validateCard($field) {
$cardNumber = $field['card'];
// Here, perform your logic and return a boolean
}
}
Also, make sure in your view, you're using the FormHelper to output the form inputs and everything should play nice. For example;
<?php
echo $this->Form->create();
echo $this->Form->input('User.card');
echo $this->Form->end();

Resources