// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package net.sourceforge.eclipsejetty.starter.console.command;
import net.sourceforge.eclipsejetty.starter.console.AbstractCommand;
import net.sourceforge.eclipsejetty.starter.console.ConsoleAdapter;
import net.sourceforge.eclipsejetty.starter.console.Process;
import net.sourceforge.eclipsejetty.starter.console.util.WordWrap;
/**
* Eats snacks.
*
* @author Manfred Hantschel
*/
public class SnackCommand extends AbstractCommand
{
private static final String[] ANSWERS = { //
"Thank you {user}, for the {snack}! I really like {snacks}.", //
"Yummy! How did you know that {snack} [is|are] my favorite food?", //
"I don't know, how I could ever live without [{a}|] {snack}! Thank you, {user}.", //
"Have YOU ever eaten {snacks}?", //
"No thanks, had {snacks} for breakfast.", //
"The {snack} [is|are] a bit smelly.", //
"Did you know, eating {snacks} can cause nervous tics?", //
"Where did you find the {snack}? Under your keyboard?", //
"I had [{a}|] {snack} once. Got stuck in my teeth.", //
"Did the {snack} had close contact with your underwear?", //
"And now I have to ask myself, 'Would Godzilla eat [{a}|] {snack}?'", //
"Do all {snacks} glow greenish? And what's this? [Is|Are] the {snack} growing eyes?", //
"[Isn't|Aren't] the {snack} looking a bit antiquarian? [Is's|They're] growing hair!", //
"[Does|Do] the {snack} have a best before date? It seems to try hiding from me!", //
"Put [that|these] {snack} away, {user}! Chuck Norris was eaten by [{a}|] {snack}.", //
"I hope the {snack} [does|do] not attack me!", //
"Good. Out of the door, line on the left, one {snack} each.", //
"Cut down a tree with [{a}|] {snack}? It can't be done.", //
"Indeed, this [is|are] [{a}|] tasty {snack}!", //
"Praise the holy {snack}!", //
"{User}, do you know what they call [{a}|] {snack} with cheese in Paris?", //
"A little more caution from you; that [is|are] no {snack} you carry.", //
"Nobody's looking for [{a}|] {snack} in today's wintry economic climate.", //
"I love the smell of {snack} in the morning...", //
"And in the morning, I'm making {snack}!",};
private static final String VOCALS = "aeiou";
public SnackCommand(ConsoleAdapter consoleAdapter)
{
super(consoleAdapter, "snack", "give");
}
/**
* {@inheritDoc}
*
* @see net.sourceforge.eclipsejetty.starter.console.Command#getFormat()
*/
public String getFormat()
{
return "[something]";
}
/**
* {@inheritDoc}
*
* @see net.sourceforge.eclipsejetty.starter.console.Command#getDescription()
*/
public String getDescription()
{
return "Give your Jetty a snack.";
}
/**
* {@inheritDoc}
*
* @see net.sourceforge.eclipsejetty.starter.console.AbstractCommand#getHelpDescription()
*/
@Override
protected String getHelpDescription()
{
return "Give your Jetty a snack. I hope it likes it.";
}
/**
* {@inheritDoc}
*
* @see net.sourceforge.eclipsejetty.starter.console.Command#getOrdinal()
*/
public int getOrdinal()
{
return -1;
}
/**
* {@inheritDoc}
*
* @see net.sourceforge.eclipsejetty.starter.console.Command#execute(java.lang.String,
* net.sourceforge.eclipsejetty.starter.console.Process)
*/
public int execute(String commandName, Process process)
{
StringBuilder builder = new StringBuilder();
for (String arg : process.args)
{
if (builder.length() > 0)
{
builder.append(" ");
}
builder.append(arg);
}
String snack = builder.toString();
if (snack.length() == 0)
{
snack = "snack";
}
String answer = ANSWERS[checksum(snack) % ANSWERS.length];
answer = replace(answer, "user", uppercase(System.getProperty("user.name")));
boolean plural = isPlural(snack);
if (plural)
{
answer = choice(answer, 1);
answer = replace(answer, "snack", snack);
answer = replace(answer, "snacks", snack);
}
else
{
boolean startsWithVocal = isVocal(snack.charAt(0));
answer = choice(answer, 0);
if (startsWithVocal)
{
answer = replace(answer, "a", "an");
}
else
{
answer = replace(answer, "a", "a");
}
answer = replace(answer, "snack", snack);
answer = replace(answer, "snacks", toPlural(snack));
}
process.out.println(new WordWrap().perform(answer.replaceAll(" +", " "), consoleAdapter.getLineLength()));
return 0;
}
private boolean isVocal(char c)
{
return VOCALS.indexOf(Character.toLowerCase(c)) >= 0;
}
private boolean isVocal(String s, int index)
{
if ((index < 0) || (index >= s.length()))
{
return false;
}
return isVocal(s.charAt(index));
}
private String cut(String s, int index)
{
if ((index < 0) || (index >= s.length()))
{
return s;
}
return s.substring(0, index);
}
private boolean isPlural(String s)
{
if (s.toLowerCase().endsWith("ss"))
{
return false;
}
return endsWith(s.toLowerCase(), "s", "men", "mice", "feet", "teeth");
}
private String toPlural(String s)
{
if (s.toLowerCase().endsWith("man"))
{
return s.substring(0, s.length() - 2) + "en";
}
if (s.toLowerCase().endsWith("mouse"))
{
return s.substring(0, s.length() - 4) + "ice";
}
if (s.toLowerCase().endsWith("foot"))
{
return s.substring(0, s.length() - 3) + "eet";
}
if (s.toLowerCase().endsWith("tooth"))
{
return s.substring(0, s.length() - 4) + "eeth";
}
if (s.toLowerCase().endsWith("y"))
{
if (!isVocal(s, s.length() - 2))
{
return s + "s";
}
return cut(s, s.length() - 1) + "ies";
}
if (endsWith(s.toLowerCase(), "ch", "s", "sh", "x", "z"))
{
return s + "es";
}
if ((s.toLowerCase().endsWith("f")) && (!s.toLowerCase().endsWith("ff")))
{
return s.substring(0, s.length() - 1) + "ves";
}
if (s.toLowerCase().endsWith("fe"))
{
return s.substring(0, s.length() - 2) + "ves";
}
return s + "s";
}
private boolean endsWith(String s, String... endings)
{
for (String ending : endings)
{
if (s.endsWith(ending))
{
return true;
}
}
return false;
}
private String replace(String s, String pattern, String replacement)
{
s = s.replace("{" + pattern + "}", replacement);
s = s.replace("{" + uppercase(pattern) + "}", uppercase(replacement));
return s;
}
private String uppercase(String s)
{
if (s.length() <= 0)
{
return s;
}
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
private static String choice(String s, int choice)
{
StringBuilder builder = new StringBuilder();
int start = 0;
while (true)
{
int index = s.indexOf('[', start);
if (index < 0)
{
builder.append(s.substring(start));
return builder.toString();
}
else
{
builder.append(s.substring(start, index));
String[] choices = s.substring(index + 1, s.indexOf(']', start)).split("\\|");
if (choice < choices.length)
{
builder.append(choices[choice]);
}
start = s.indexOf(']', start) + 1;
}
}
}
private static int checksum(String s)
{
int sum = 0;
for (int i = 0; i < s.length(); i += 1)
{
sum = (sum << 1) + s.charAt(i);
}
return sum;
}
}