

var formflds= ['cname','pandp','cones','obst1','obst2','obst3','obst4','total','place','notes'];     //names on the html form


//acceptable formats - list of header column names. Where a column is an array, it means find the first one of these columns and the real one is the enxt one after it.
var xlheaders = [
['name','score','total','obs 1','obs 2','obs 3','obs 4',['total','total'],'place'],
['name','score','cones','obs 1','obs 2','obs 3','obs 4','total','place'],
['name','p&p total','cones total','obs1','obs2','obs3','obs4','total','place final','notes'],
['competitor name',['class','p&p'],'cones','ob1','ob2','ob3','ob4','total','place','notes'],
['competitor name','p&p','cones','ob1','ob2','ob3','ob4','total','place'],
['driver','p & p score','cones score','obs1 total','obs2 total','obs3 total','obs4 total','overall total','place','notes'],
['comp. name','total','cones','obs 1','obs 2','obs 3','obs 4','total','place'],
['driver',['class','dress score'],'cones score','obs 1','obs 2','obs 3','obs 4','final score','final place','notes'],
['competitor','p & p score','cones score','obs 1','obs 2','obs 3','obs 4','all phases','final place'],
['competitor','p & p','cones','obs.1','obs.2','obs.3','obs.4','total','final place'],

];

var PLACECOL = 8;

var rows;

var iclasscol = -1;   //if this score format has a separate class column this will be set

var xlcols = [];

var iheaderrow = -1;

var iclasses = [];

var iheadertype = -1;   //which header we found


//----------------------------------------------------------------------//
function iImportXl()
{
var s = iGetClipboard();
var smsg = "You need to:\n- go into Excel\n- open your scoresheet\n- select the scores and\n- press Edit Copy (or Ctrl C) first\n- then press Paste on this form\n\n";

if (!s || s.length < 2) {
  alert("I didn't see any data\n\n" + smsg);
  return;
  }

var lines = s.split("\n");

iFindClasses('class01');      //this loads class array from the select list named here

if (iAnalyseCols(lines) < 0) {
  alert("Sorry, I couldn't find a header column I understand.\n\n" + smsg + "I can't import this data:-\n\n" + s);
  return;
  }

if (!confirm("Ready to paste in your data.\n\nThis will overwrite anything already entered in the scores on this page.\n\nClick OK to continue. Click Cancel to stop.")) return;


  rows = new Array();
  rows.iclass = -1;        //no class known yet

  iImportRows(lines, rows);

  iWriteToForm(rows);
}
//----------------------------------------------------------------------//
function iImportRows(lines, rows)
{
var imax = lines.length;
var i;

  if (iclasscol > -1) {
    i = iheaderrow+1;
    }
  else {
    i = iheaderrow-2;   //some formats I need to start above the header row to catch the class
    if (i < 0) i = 0;
    }

//   if (iheadertype ==6) {    //Martyn Willis/Sue Courtney xl?
//     i = iheaderrow + 1;
//     iclasscol = 0;
//     }


  for (;i<imax;i++) {
    iImportOneRow(lines[i],rows);
    }
}
//----------------------------------------------------------------------//
function iImportOneRow(sline)
{
 var flds = iLineToFlds(sline);           //split up the line
 var sname = flds[xlcols[0]];     //name or class
 var list;
 var i;

 if (!sname || sname == '') return;


  if (sname.toLowerCase()=='class:') return;    //ignore
  if (sname.toLowerCase()=='class') return;    //ignore
  if (sname.toLowerCase()=='judge') return;    //ignore

  if (sname.toLowerCase()==xlheaders[iheadertype][0]) return;    //ignore - it's a repeat of the header column


 if ((flds[xlcols[2]]=='') && (flds[xlcols[8]]=='')) {   //probably a class name - no P&p or placing
   if (iclasscol > -1) return;    //if class is in a column we will read it separately
   i = iMatchClass(sname);
   if (i >= 0) {
     rows.iclass = i;
     }
    return;
    }

                            //here for a normal data row
  if (iclasscol > -1) {     //get class from the data column
    sname = flds[iclasscol];
    if (sname != '') {         //some formats just show the class once
      i = iMatchClass(sname);
      if (i >= 0) {
        rows.iclass = i;
        }
       }
     }
  if (flds[xlcols[0]].toLowerCase()=='0') return;    //ignore drivers called 0

                                           ///here to save a new row
   var irow = rows.length;
   rows[irow] = new Array();

   for (i=0;i<xlcols.length;i++) {
     rows[irow][i] = flds[xlcols[i]];   //fill in the fields
     }
   rows[irow].iclass = rows.iclass;

}
//----------------------------------------------------------------------//
function iWriteToForm()
{
  var sseq;
  var iformrow = 1;
  var irow;
  var irowmax = rows.length;
  var iclass = -1;

  rows.sort(iPlaceSort);

  for (irow=0; irow < irowmax; irow++) {

    if (iformrow < 10) {
      sseq = '0' + iformrow;    //pad to two digits
      }
    else {
      sseq = iformrow;
      }

    if (rows[irow].iclass != iclass) {      //new class
       iclass = rows[irow].iclass;
       iSelectOptionByValue('class' + sseq, iclass);
       }

     for (i=0;i<xlcols.length;i++) {
       document.getElementById(formflds[i] + sseq).value = rows[irow][i];   //fill in the fields
       }
    iformrow++;
  }
}
//------------------------------------------------------------------------------------------------------------------
function iPlaceSort(a,b)    //compares rows i and j
{
 if (a.iclass > b.iclass) return 1;     //first part of sort is on the class
 if (a.iclass < b.iclass) return -1;

 var na,nb,sa,sb;

 na = sa = a[PLACECOL];    //text versions of the values to compare
 nb = sb = b[PLACECOL];    //if the palcing goes above 10 we need to be careful to do number compare not text (else 10 < 2)

 try {
   na = parseInt(sa);      //try to use it as a number - if not fall back to text (it might be r or wd etc
   } catch (e) {}

  if (isNaN(na)) na = sa;
  else {
     try {
       nb = parseInt(sb);      //try to use it as a number - if not fall back to text (it might be r or wd etc
       } catch (e) {}
      if (isNaN(nb)) {        //we need them both numbers or both text
        nb = sb;
        na = sa;
        }
      }

 if (na > nb) return 1;   //within a class we sort by placing
 if (na < nb) return -1;

 return 0;     //equal
}
//----------------------------------------------------------------------//
function iAnalyseCols(lines)
//try each acceptable type of format until we match one or give up
{
var imax = xlheaders.length;

try {
  for (i=0;i<imax;i++) {
    if (iTryOneHeaderType(lines,xlheaders[i])) {
      iheadertype = i;
      return i;
      }
    }
} catch(e) {}

return -1;
}
//----------------------------------------------------------------------//
function iTryOneHeaderType(lines,xlhdr)
//see if the named columns appear in the data in the specified order
//if so return true with the column map set up,
//else false
{
var icol = 0;             //start at column 0

icol = ifindName(lines,xlhdr[0]);
if (icol < 0) return false;      //first we look for the name column - that decides which row to use

xlcols[0] = icol;     //save the mapping - provisionally

if (iTryHeader(lines,xlhdr,icol)) return true;    //see if the rest of the header is on the same line

iheaderrow++;      //else try the next one

if (iTryHeader(lines,xlhdr,icol)) return true;    //see if the rest of the header is on the same line

return false;   //no luck
}
//----------------------------------------------------------------------//
function iTryHeader(lines,xlhdr,icol)
{
var imax = xlhdr.length;

for (var i=1;i<imax;i++) {
  if (ilibIsArray(xlhdr[i])) {     //we accept an array of two fields as one element, meaning find first and discard, use second
    icol = ifindhcol(lines,icol,xlhdr[i][0]);
    if (icol <0) return false;
    if (xlhdr[i][0] == 'class') {
      iclasscol = icol;          //this was a separate class column - save it's column number separately
      }
    icol++;
    icol = ifindhcol(lines,icol,xlhdr[i][1]);
    }
  else {
    icol = ifindhcol(lines,icol,xlhdr[i]);
    }
  if (icol <0) return false;
  xlcols[i] = icol;     //save the mapping
  icol++;
  }
return true;      //success
}
//----------------------------------------------------------------------//
function ifindName(lines,s)
//find the header row - it must have at least the fields supplied
{
var irow,i,iname;

  for (i = 0;i<=5;i++) {      //try the first 6 rows
    iname = ifindcol(lines,i,0,s);
    if (iname >= 0) {   //if 'name' found, this might be the row
       iheaderrow = i;          //save it in a global - hmm, fine style
       return iname;
       }
     }
return -1;      //not found
}
//----------------------------------------------------------------------//
function ifindhcol(lines,colmin,snam)
//look in the header row for a named field
{
return ifindcol(lines,iheaderrow,colmin,snam);
}
//----------------------------------------------------------------------//
function ifindcol(lines,irow,colmin,snam)
//search for a column name - first row which has it
{
var j,jmax,flds;

snam = snam.toLowerCase();    //case independent check

try {
  flds = iLineToFlds(lines[irow]);           //split up the line

  jmax = flds.length;
  for (j=colmin;j<jmax;j++) {
    if (flds[j].toLowerCase() == snam) {
        return j;
        }
      }
    }  catch (e) {}

return -1;    //no luck
}
//----------------------------------------------------------------------//
function iMatchClass(sclass)
//do our best to match users class to the classnames we know
{
var icl,i;


if (!sclass || sclass.length < 4) {
  alert("I don't recognise class '" + sclass + "'\n\nPlease use a class which matches my pulldown class list.");
  return -1;    //not a legal class
  }

sclass = sclass.toLowerCase();

if (sclass.substring(0,5)=='ihdt ') sclass = sclass.slice(5);   //some users prefix the class name with ihdt (!)

if (sclass.substring(0,4)=='club') sclass = 'club';   //some users have various club classes



if (sclass=='pair') {
  sclass = 'multiples - pairs';
  }
else if (sclass=='tandem') {
  sclass = 'multiples - tandems';
  }
else if (sclass=='multiples') {
  sclass = 'multiples (combined)';
  }


icl = iFindStringInArray(sclass, iclasses);     //see if an exact match

if (icl >= 0) return icl;   //exact match

icl = iFindStringInArray(sclass + 's', iclasses);     //see if an exact match this catches where scores says Pony pair and we expect Pony pairS etc

if (icl >= 0) return icl;   //exact match


var imax = iclasses.length;


  myval = iStartAndEnd(sclass,4);     //try match on first and last four letters - helps with Open Single Pony etc

  for (i=0;i<imax;i++) {
    if (!iclasses[i] || iclasses[i]=='') continue;
    if (iStartAndEnd(iclasses[i],4) == myval) return i;       //found it
    }


  if (sclass == 'multiple') return  iFindStringInArray('Multiples (Combined)', iclasses);
  if (sclass == 'multiplies') return  iFindStringInArray('Multiples (Combined)', iclasses);     //common typo ?!

     alert("I don't recognise class '" + sclass + "'\n\nPlease use a class which matches my pulldown class list.");

return -1;    //no match
}
//----------------------------------------------------------------------//
function iStartAndEnd(s,ilen)
//get the ilen first and ilen last letters of s atring for partial match
{
  if (!s) return '';
  var iend = s.length - ilen - 1;
  if (iend < 0) iend = 0;

  return (s.substring(0,ilen) + s.substring(iend)).toLowerCase();
}
//----------------------------------------------------------------------//
function iFindClasses(sid)
//find the classes from the classes pulldown on the page
{
var list = document.getElementById(sid);

var l = list.options.length;

  for (var i = 0; i < l; i++) {
    iclasses[list.options[i].value] = list.options[i].text;
    }
}
//----------------------------------------------------------------------//
function ilibIsArray(o)
//return true if array else false
{
return (o instanceof Array);
}
//----------------------------------------------------------------------//
function iFindStringInArray(myval, myarray)
//return the index of the value in the given array, or -1 if not found
//note this version ignores blank/null strings
{
try {
  myval = myval.toLowerCase();

  var imax = myarray.length;
  for (var i=0;i<imax;i++) {
    if (!myarray[i]) continue;
    if (myarray[i].toLowerCase() == myval) return i;       //found it
    }
  } catch (e) {}
return -1;      //not found
}
//------------------------------------------------------------------------------------------------------------------
function iLineToFlds(sline)
{
  var flds = sline.split("\t");           //assume tab delimiter

  var i = flds.length -1;   //last element in flds probably has a linefeed in it

  flds[i] = iStripNewlines(flds[i]);

  return flds;
}
//------------------------------------------------------------------------------------------------------------
//strip any newline sequences
function iStripNewlines(s) {
  var reCR = new RegExp(String.fromCharCode(13), 'g');
  var reLF = new RegExp(String.fromCharCode(10), 'g');

  return s.replace(reCR, '').replace(reLF, '');
}
//------------------------------------------------------------------------------------------------------------
function iSelectOptionByValue(sname,myval)
//for a selct list, find the optin whose value matches myval and set it selected
{
var  list = document.getElementById(sname);

var imax = list.options.length;

  for (var i=0;i<imax;i++) {
    if (list.options[i].value == myval) {
      list.selectedIndex = i;
      return;
      }
    }
}
//------------------------------------------------------------------------------------------------------------

