var nv0 = new Array(-50, -100, -150, -200, -250, -300, -350, -400, -450, -500, -550, -600, -650);
var v0 = new Array(-100, -200, -300, -400, -500, -600, -700, -800, -900, -1000, -1100, -1200, -1300);
var nvx = new Array(-100, -300, -500, -800, -1100, -1400, -1700, -2000, -2300, -2600, -2900, -3200, -3500);
var vx = new Array(-200, -500, -800, -1100, -1400, -1700, -2000, -2300, -2600, 2900, -3200, -3500, -3800);
var nvxx = new Array(-200, -600, -1000, -1600, -2200, -2800, -3400, -4000, -4600, -5200, -5800, -6400, -7000);
var vxx = new Array(-400, -1000, -1600, -2200, -2800, -3400, -4000, -4600, -5200, -5800, -6400, -7000, -7600);
var v0 = new Array(-100, -200, -300, -400, -500, -600, -700, -800, -900, -1000, -1100, -1200, -1300);
var nvx = new Array(-100, -300, -500, -800, -1100, -1400, -1700, -2000, -2300, -2600, -2900, -3200, -3500);
var vx = new Array(-200, -500, -800, -1100, -1400, -1700, -2000, -2300, -2600, 2900, -3200, -3500, -3800);
var nvxx = new Array(-200, -600, -1000, -1600, -2200, -2800, -3400, -4000, -4600, -5200, -5800, -6400, -7000);
var vxx = new Array(-400, -1000, -1600, -2200, -2800, -3400, -4000, -4600, -5200, -5800, -6400, -7000, -7600);
/*
While overtricks in undoubled contracts are each worth the same number of points as the trick taken before them, doubled and redoubled overtricks are not linear. Furthermore, the first trick over book in No Trump contracts is worth more than the rest, which is easy enough to code ; however, I chose again to go with arrays. Note that, as suggested earlier, these figures only apply to the tricks that taken in completion of a specified made contract. Overtricks are calculated later.
*/
While overtricks in undoubled contracts are each worth the same number of points as the trick taken before them, doubled and redoubled overtricks are not linear. Furthermore, the first trick over book in No Trump contracts is worth more than the rest, which is easy enough to code ; however, I chose again to go with arrays. Note that, as suggested earlier, these figures only apply to the tricks that taken in completion of a specified made contract. Overtricks are calculated later.
*/
var bidtrickminor = new Array(20, 40, 60, 80, 100, 120, 140);
var bidtrickmajor = new Array(30, 60, 90, 120, 150, 180, 210);
var bidtricknt = new Array(40, 70, 100, 130, 160, 190, 220);
var bidtrickmajor = new Array(30, 60, 90, 120, 150, 180, 210);
var bidtricknt = new Array(40, 70, 100, 130, 160, 190, 220);
/*
This final global variable lists all possible results of all possible contracts, from the 1 level to the 7 level. A 7-level contract can go down 13, and a 1-level contract can make six overtricks. The value of this will become clear in the first three functions.
*/
This final global variable lists all possible results of all possible contracts, from the 1 level to the 7 level. A 7-level contract can go down 13, and a 1-level contract can make six overtricks. The value of this will become clear in the first three functions.
*/
var resVal = new Array("-13", "-12", "-11", "-10","-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "=", "+1", "+2", "+3", "+4", "+5", "+6");
/*
I really like this one. The menu() function is called whenever the level is changed. It abbreviates a couple long addresses to information and defines selection to be equal to "7-(level-0)"; this second point allows it to set the new values and display "=" when it makes the change. Also, since the value attribute of an option element is seen as a text data type, and because there is no texttonum() function in Javascript, subtracting 0 is the only way to force the conversion of a number into the numeric data type without changing it.
The fun part comes next. It defines the text values (what the user sees) of the level menu, drawing its values from the ressulttext array above. By subtracting the level from a series of numbers beginning with 20 (the number of values in the array), it picks the proper text to display for each outcome. If you look at the .html file, you will see that the value for each position in the array remains constant, corresponding to the number of tricks won. Beginning with version (1.4), this is handled by a for() loop (2 lines) rather than individual statements for each option (14 lines).
*/
I really like this one. The menu() function is called whenever the level is changed. It abbreviates a couple long addresses to information and defines selection to be equal to "7-(level-0)"; this second point allows it to set the new values and display "=" when it makes the change. Also, since the value attribute of an option element is seen as a text data type, and because there is no texttonum() function in Javascript, subtracting 0 is the only way to force the conversion of a number into the numeric data type without changing it.
The fun part comes next. It defines the text values (what the user sees) of the level menu, drawing its values from the ressulttext array above. By subtracting the level from a series of numbers beginning with 20 (the number of values in the array), it picks the proper text to display for each outcome. If you look at the .html file, you will see that the value for each position in the array remains constant, corresponding to the number of tricks won. Beginning with version (1.4), this is handled by a for() loop (2 lines) rather than individual statements for each option (14 lines).
*/
function menu()
{
{
level = document.info.level.value;
sel = 7-(level-0);
res = document.info.result.options;
for (i = 0; i < 14; i++)
}
sel = 7-(level-0);
res = document.info.result.options;
for (i = 0; i < 14; i++)
res[i].text = resVal[(20 - i) - level];
res[sel].selected = true;
/*
The parent() function is the parent of the down() and made() functions. It decides which one gets called to calculate a score. It begins by defining five shorthand names for the values in the widget's menus. Once that is done, it asks whether the number of tricks taken (expressed as "result") is less than the number of tricks bid (expressed as "result < ((level-0)+6)"). If so, it calls the down() function, passing the necessary data to it; otherwise, it calls the made() function and passes those data it needs.
*/
The parent() function is the parent of the down() and made() functions. It decides which one gets called to calculate a score. It begins by defining five shorthand names for the values in the widget's menus. Once that is done, it asks whether the number of tricks taken (expressed as "result") is less than the number of tricks bid (expressed as "result < ((level-0)+6)"). If so, it calls the down() function, passing the necessary data to it; otherwise, it calls the made() function and passes those data it needs.
*/
function score()
{
{
level = (document.forms[0].level.value)-0;
X = document.forms[0].X.value;
vul = document.forms[0].vulnerability.value;
result = document.forms[0].result.value;
denom=document.forms[0].denomination.value
if (result < ((level-0)+6))
}
X = document.forms[0].X.value;
vul = document.forms[0].vulnerability.value;
result = document.forms[0].result.value;
denom=document.forms[0].denomination.value
if (result < ((level-0)+6))
down(result, X, vul);
else
made(level, denom, X, vul, result);
/*
This one is pretty simple. It uses a series of conditional statements to check the vulnerability and doubled status of the contract so it can determine which of the undertrick arrays to use. It then writes the proper value to a blank div tag in the .html file via document.getElementById.
The reason for subtracting 5 from the result is simple. First, remember that Javascript arrays begin with element number 0. Now, since the level is the number of tricks above 6 declarer must win, we need to reduce the result (which looks at total tricks taken) by 6. However, since a contract going down by one trick needs to address array element 0, we need to subtract a larger number from the level, hence we subtract 5 from result, instead of subtracting 6.
*/
This one is pretty simple. It uses a series of conditional statements to check the vulnerability and doubled status of the contract so it can determine which of the undertrick arrays to use. It then writes the proper value to a blank div tag in the .html file via document.getElementById.
The reason for subtracting 5 from the result is simple. First, remember that Javascript arrays begin with element number 0. Now, since the level is the number of tricks above 6 declarer must win, we need to reduce the result (which looks at total tricks taken) by 6. However, since a contract going down by one trick needs to address array element 0, we need to subtract a larger number from the level, hence we subtract 5 from result, instead of subtracting 6.
*/
function down(result, X, vul)
{
{
if (vul=="nv" && X=="n")
}
document.getElementById("score").innerHTML = nv0[(level-0)-(result-5)];
else if (vul=="nv" && X=="x")
document.getElementById("score").innerHTML = nvx[(level-0)-(result-5)];
else if (vul=="nv" && X=="xx")
document.getElementById("score").innerHTML = nvxx[(level-0)-(result-5)];
else if (vul=="v" && X=="n")
document.getElementById("score").innerHTML = v0[(level-0)-(result-5)];
else if (vul=="v" && X=="x")
document.getElementById("score").innerHTML = vx[(level-0)-(result-5)];
else
document.getElementById("score").innerHTML = vxx[(level-0)-(result-5)];
/*
The made() function first looks at the value of the denomination selection to determine which of the "bidtrick" arrays to use (minor, major or nt), assigning the value to the local "den" variable. It then runs through a check of the doubled status to determine whether to award straight points, double points, or quadruple points for the tricks that apply to the level of the contract. This is the base score for a making contract. Note that once again we need to reduce the value (this time of "level") by one because arrays begin with element 0.
It then determines how many overtricks were taken and computes, based upon the denomination (if undoubled) or the doubled status, what multiplier to apply. The joy here is that 0 overtricks returns the proper result, so it is not necessary to determine first whether or not a made contract included any overtricks. With a little poking about, you can see how the multipliers work.
The next two steps involve determining what bonuses to apply for part score, game, and slam. In duplicate bridge, even a making part score earns a bonus. A slam or grand slam also earns the bonus for the underlying game, so these get calculated separately.
The last component of score is the bonus for making a doubled or redoubled contract, worth 50 and 100 points, respectively. This is unaffected by the level or denomination.
Finally, it adds all five values together and assigns them to that blank div tag we saw mentioned in down().
*/
The made() function first looks at the value of the denomination selection to determine which of the "bidtrick" arrays to use (minor, major or nt), assigning the value to the local "den" variable. It then runs through a check of the doubled status to determine whether to award straight points, double points, or quadruple points for the tricks that apply to the level of the contract. This is the base score for a making contract. Note that once again we need to reduce the value (this time of "level") by one because arrays begin with element 0.
It then determines how many overtricks were taken and computes, based upon the denomination (if undoubled) or the doubled status, what multiplier to apply. The joy here is that 0 overtricks returns the proper result, so it is not necessary to determine first whether or not a made contract included any overtricks. With a little poking about, you can see how the multipliers work.
The next two steps involve determining what bonuses to apply for part score, game, and slam. In duplicate bridge, even a making part score earns a bonus. A slam or grand slam also earns the bonus for the underlying game, so these get calculated separately.
The last component of score is the bonus for making a doubled or redoubled contract, worth 50 and 100 points, respectively. This is unaffected by the level or denomination.
Finally, it adds all five values together and assigns them to that blank div tag we saw mentioned in down().
*/
function made(level, denom, X, vul, result)
{
{
if (denom=="minor")
if (X=="n")
if (X=="n" && denom=="minor")
if (base >= 100 && vul=="nv")
if (level == 6 && vul=="nv")
if (X=="x")
document.getElementById("score").innerHTML = (base + ot + gamebonus + slambonus + xbonus);
}
den = bidtrickminor;
else if (denom=="major")
den = bidtrickmajor;
else
den = bidtricknt;
if (X=="n")
base = den[level - 1];
else if (X=="x")
base = 2 * (den[level - 1]);
else
base = 4 * (den[level - 1]);
if (X=="n" && denom=="minor")
ot = (result -((level-0)+6)) * 20;
else if (X=="n" && (denom=="major" || denom=="nt"))
ot = (result -((level-0)+6)) * 30;
else if (vul=="nv" && X=="x")
ot = (result -((level-0)+6)) * 100;
else if ((vul=="v" && X=="x") || (vul=="nv" && X=="xx"))
ot = (result -((level-0)+6)) * 200;
else
ot = (result -((level-0)+6)) * 400;
if (base >= 100 && vul=="nv")
gamebonus = 300;
else if (base >= 100 && vul=="v")
gamebonus = 500;
else
gamebonus = 50;
if (level == 6 && vul=="nv")
slambonus = 500;
else if (level == 6 && vul=="v")
slambonus = 750;
else if (level == 7 && vul=="nv")
slambonus = 1000;
else if (level == 7 && vul=="v")
slambonus = 1500;
else
slambonus = 0;
if (X=="x")
xbonus = 50;
else if (X=="xx")
xbonus = 100;
else
xbonus = 0;
document.getElementById("score").innerHTML = (base + ot + gamebonus + slambonus + xbonus);
/*
The remainder of these functions are supplied by, at least in their basic form, Apple. Only two are different enough to deserve much more comment than Apple already provides, however. Zip on down to see why.
*/
The remainder of these functions are supplied by, at least in their basic form, Apple. Only two are different enough to deserve much more comment than Apple already provides, however. Zip on down to see why.
*/
function showBack()
{
function hideBack()
{
var flipShown = false;
var animation = {duration:0, starttime:0, to:1.0, now:0.0, from:0.0, firstElement:null, timer:null};
function mousemove (event)
{
function mouseexit (event)
{
function animate()
{
function limit_3 (a, b, c)
{
function computeNextFloat (from, to, ease)
{
function enterflip(event)
{
function exitflip(event)
{
function loaded()
{
{
var front = document.getElementById("front");
var back = document.getElementById("back");
if (window.widget)
}
var back = document.getElementById("back");
if (window.widget)
widget.prepareForTransition("ToBack");
front.style.display="none";
back.style.display="block";
if (window.widget)
front.style.display="none";
back.style.display="block";
setTimeout ('widget.performTransition();', 0);
function hideBack()
{
var front = document.getElementById("front");
var back = document.getElementById("back");
if (window.widget)
}
var back = document.getElementById("back");
if (window.widget)
widget.prepareForTransition("ToFront");
back.style.display="none";
front.style.display="block";
if (window.widget)
back.style.display="none";
front.style.display="block";
setTimeout ('widget.performTransition();', 0);
var flipShown = false;
var animation = {duration:0, starttime:0, to:1.0, now:0.0, from:0.0, firstElement:null, timer:null};
function mousemove (event)
{
if (!flipShown)
{
}
{
if (animation.timer != null)
{
var starttime = (new Date).getTime() - 13;
animation.duration = 500;
animation.starttime = starttime;
animation.firstElement = document.getElementById ('flip');
animation.timer = setInterval ("animate();", 13);
animation.from = animation.now;
animation.to = 1.0;
animate();
flipShown = true;
}
{
clearInterval (animation.timer);
animation.timer = null;
}
animation.timer = null;
var starttime = (new Date).getTime() - 13;
animation.duration = 500;
animation.starttime = starttime;
animation.firstElement = document.getElementById ('flip');
animation.timer = setInterval ("animate();", 13);
animation.from = animation.now;
animation.to = 1.0;
animate();
flipShown = true;
function mouseexit (event)
{
if (flipShown)
{
}
{
// fade in the info button
if (animation.timer != null)
{
var starttime = (new Date).getTime() - 13;
animation.duration = 500;
animation.starttime = starttime;
animation.firstElement = document.getElementById ('flip');
animation.timer = setInterval ("animate();", 13);
animation.from = animation.now;
animation.to = 0.0;
animate();
flipShown = false;
}
if (animation.timer != null)
{
clearInterval (animation.timer);
animation.timer = null;
}
animation.timer = null;
var starttime = (new Date).getTime() - 13;
animation.duration = 500;
animation.starttime = starttime;
animation.firstElement = document.getElementById ('flip');
animation.timer = setInterval ("animate();", 13);
animation.from = animation.now;
animation.to = 0.0;
animate();
flipShown = false;
function animate()
{
var T;
var ease;
var time = (new Date).getTime();
T = limit_3(time-animation.starttime, 0, animation.duration);
if (T >= animation.duration)
{
else
{
animation.firstElement.style.opacity = animation.now;
}
var ease;
var time = (new Date).getTime();
T = limit_3(time-animation.starttime, 0, animation.duration);
if (T >= animation.duration)
{
clearInterval (animation.timer);
animation.timer = null;
animation.now = animation.to;
}
animation.timer = null;
animation.now = animation.to;
else
{
ease = 0.5 - (0.5 * Math.cos(Math.PI * T / animation.duration));
animation.now = computeNextFloat (animation.from, animation.to, ease);
}
animation.now = computeNextFloat (animation.from, animation.to, ease);
animation.firstElement.style.opacity = animation.now;
function limit_3 (a, b, c)
{
return a < b ? b : (a > c ? c : a);
}
function computeNextFloat (from, to, ease)
{
return from + (to - from) * ease;
}
function enterflip(event)
{
document.getElementById('fliprollie').style.display = 'block';
}
function exitflip(event)
{
document.getElementById('fliprollie').style.display = 'none';
}
function loaded()
{
var doneButton = document.getElementById("done");
createGenericButton(doneButton, "Done", hideBack);
}
createGenericButton(doneButton, "Done", hideBack);
/*
This next function is a modification of Apple's standard menu display code. Since I have four menus that just require the basic code, I wanted a way to call the same function for all four instead of using the older method of having four distinct functions.
In order to accomplish this, I added one argument ("text") to the function and used it to pass the information about which menu's information to display, which was the only piece of information that wasn't being passed using "this" in the original version.
*/
This next function is a modification of Apple's standard menu display code. Since I have four menus that just require the basic code, I wanted a way to call the same function for all four instead of using the older method of having four distinct functions.
In order to accomplish this, I added one argument ("text") to the function and used it to pass the information about which menu's information to display, which was the only piece of information that wasn't being passed using "this" in the original version.
*/
function dMenu(elem, text)
{
{
var chosenOption = elem.options[elem.selectedIndex].text;
document.getElementById(text).innerText = chosenOption;
}
document.getElementById(text).innerText = chosenOption;
/*
First of all, because I chose to use the suit symbols instead of letters, I had to encode the document as UTF-8 (TextWrangler does a nice job of recognizing and managing this). Without that step, the suits would be gibberish. It's all well and good that Apple shows me how I can make these cool menus, but I love that I can also exercise full control of the display because of how it is set up.
Since what the user sees when a menu is not active is being handled by filling a div tag, the same way we did with the score, we have control over every aspect of the displayed text. Suit symbols are smaller than normal characters, so normally "NT" looks disproportionately large. The solution is to specify the positioning, font-family, color, and size for each possible result. This allows the menu to make the most of its space without tripping over symbols that render differently. Note that everything must be specified every time; otherwise, the unchanged parameters will carry over, which could have unintended results.
*/
First of all, because I chose to use the suit symbols instead of letters, I had to encode the document as UTF-8 (TextWrangler does a nice job of recognizing and managing this). Without that step, the suits would be gibberish. It's all well and good that Apple shows me how I can make these cool menus, but I love that I can also exercise full control of the display because of how it is set up.
Since what the user sees when a menu is not active is being handled by filling a div tag, the same way we did with the score, we have control over every aspect of the displayed text. Suit symbols are smaller than normal characters, so normally "NT" looks disproportionately large. The solution is to specify the positioning, font-family, color, and size for each possible result. This allows the menu to make the most of its space without tripping over symbols that render differently. Note that everything must be specified every time; otherwise, the unchanged parameters will carry over, which could have unintended results.
*/
function denomChanged(elem)
{
{
var chosenOption = elem.options[elem.selectedIndex].text;
document.getElementById("denTxt").innerText = chosenOption;
if (elem.options[elem.selectedIndex].text == "♦")
{
else if (elem.options[elem.selectedIndex].text == "♥")
{
else if ((elem.options[elem.selectedIndex].text == "♣") || (elem.options[elem.selectedIndex].text == "♠"))
{
else
{
}
document.getElementById("denTxt").innerText = chosenOption;
if (elem.options[elem.selectedIndex].text == "♦")
{
document.getElementById("denTxt").style.color = "red";
document.getElementById("denTxt").style.fontSize = "21px";
document.getElementById("denTxt").style.top = "23px";
}
document.getElementById("denTxt").style.fontSize = "21px";
document.getElementById("denTxt").style.top = "23px";
else if (elem.options[elem.selectedIndex].text == "♥")
{
document.getElementById("denTxt").style.color = "red";
document.getElementById("denTxt").style.fontSize = "14px";
document.getElementById("denTxt").style.top = "29px";
}
document.getElementById("denTxt").style.fontSize = "14px";
document.getElementById("denTxt").style.top = "29px";
else if ((elem.options[elem.selectedIndex].text == "♣") || (elem.options[elem.selectedIndex].text == "♠"))
{
document.getElementById("denTxt").style.color = "black";
document.getElementById("denTxt").style.fontSize = "16px";
document.getElementById("denTxt").style.top = "27px";
}
document.getElementById("denTxt").style.fontSize = "16px";
document.getElementById("denTxt").style.top = "27px";
else
{
document.getElementById("denTxt").style.color = "white";
document.getElementById("denTxt").style.fontSize = "16px";
document.getElementById("denTxt").style.top = "27px";
}
document.getElementById("denTxt").style.fontSize = "16px";
document.getElementById("denTxt").style.top = "27px";
Undertricks are only linear when undoubled, so doubled and redoubled values are best stored in arrays. Since that accounts for four of six possible sets of undertrick values, I opted to create arrays for all six. We will see, when we look at down(), why this is useful. The names refer to non-vulnerable (nv) and vulnerable (v) for undoubled (0), doubled (x), and redoubled (xx) states.
*/