Insane in the membrane April 12, 2016 at 7:26 am
Amusing, but is still understating the issue March 10, 2016 at 11:15 pm
What is wrong with our country? March 1, 2016 at 11:45 pm
We must be largely mentally ill. Are we seriously considering Donald J Drumpf as the leader of our country? I know that many of our politicians have issues, but I really think we need to draw a line. On one hand A Drumpf/Palin run would take us a long way towards the prophecy of Idiocracy. What is even funnier? I typed ‘Idiocracy’ into ‘the Google’ to make sure I had the spelling correct and that association was already made. At least some people are starting to think, but I was more than a bit nervous about McCain/Palin, but (IMO) our country woke up before it was too late.
The Kindle is dead, Long live the Kindle! April 20, 2015 at 7:45 pm
Sometimes ya just gotta wonder ’bout things.
This is the third Kindle I have murdered. I don’t THINK I am especially evil to my hardware, but wow.
On one hand this was a Gen 1 Paperwhite AND I had considered getting a Voyage when it was announced, however the Paperwhite was just fine and I really didn’t NEED a new device. (Not like that has really ever stopped me in the past!) I had put off dealing with it for a while and last night the ‘watershed moment’ happened. I launched that puppy off of a towel I set the device on. Something about hitting the corner on a tile floor from at least 5-6 feet in the air didn’t agree with the touch screen. Like previously destroyed devices this shattered the touch screen enough to render it unusable.
Last week Apple did me a solid and replaced a battery on my iPhone 5 under warranty. I was ‘kinda’ hoping that I would ‘have’ to buy an iPhone 6, but alas instead they just made me a more loyal customer. In all fairness, Amazon did the same with the second of 2 K3’s that got killed too. Something tells me that an assisted launch of a Kindle isn’t really a warranty event. At least this one lasted a couple of years.
I am not all that unhappy about it, and I REALLY didn’t do it on purpose. :-O
10 Years to the Day … Weird April 13, 2015 at 1:20 pm
For some reason today I was going ‘back in time’ reading over my BLOG. This whole thing has started / stopped / started / sputtered, and has mostly been ‘Meh’ overall. There really isn’t a coherent theme, and other than ‘bot traffic’ AFAIK I am really the only person that pays it much attention. I know it gets indexed and I know every now and then someone spends a little time here, but not overly so.
So I REALLY didn’t plan this AND I went ALL the way back in time (as far as THIS BLOG is concerned). Wow, 10 years ago I was sitting in Miami (Most likely Miami Beach ~and~ most likely at my desk in my SOON to fail business, the writing WAS clearly on the wall, but it wasn’t long after I started the blog when the final decision was made by me to pack it in.)
This blog was more or less ‘started on a whim’ (as I remember it) because some ‘folks that I knew’ had basically rolled out a blogging service many months prior and I figured, what the heck. (I actually DID ~know~ a few of the people that worked on it, as in like personally met them, but couldn’t tell you who they are NOW. Sad really, but that is life.)
During ‘its’ life, the blog has transitioned between (I am fairly sure it ~was~ originally MSN, as that would have put me in contact with ‘folks that worked on it’) at least 4 different groups at MS, and another host when MS shut down. I ~think~ the last iteration was called ‘Live Spaces’. I didn’t make notes on all of that so reality is that I am likely wrong.
Wow. Something that has some fairly interesting (to me anyway) key focal points of my life preserved. I didn’t really BLOG about most of my ‘failures’ but I can see the initial cracks that started the avalanches.
Nor have I written about ALL of my successes either, but I can see some of those obliquely preserved too! (It is ALL about context.)
The weird part? Todays entry wouldn’t even EXIST unless I was triggered to look at the content by an exceptionally weird confluence of butterfly wings flapping. Even then, deciding to LOOK AT my very first entry wasn’t a conscious decision! That to me is THE MOST odd part. Completely unplanned.
Weird. (And Wow, 10 friggin’ years TO THE DAY. Kinda neet?) Weird.
I wonder right this minute what the future holds. I have noticed more than one subtle observation that has turned out to be ~major~ themes in my life AND I didn’t understand the ramifications of the observations AT THE TIME. I am loath to make any other observations right now because of that. You know, ‘jinx’ things, because THAT would be science. 😉
Columnized text in Minecraft Chat February 4, 2015 at 8:11 pm
Minecraft uses variable width fonts in the chat output during gameplay. For plugins that benefit from displaying tables of data this will cause issues. It isn’t possible to just use spaces to align columns of data. Any text that contains characters outside of the ‘normal width’ will cause columns to be pushed to one side or the other.
Most characters are equivalent to six pixels in width. The ones that cause problems are not the same width. The biggest troublemaker is ‘space’. A space is rendered equivalent to four pixels wide. You could almost ‘fix’ the problem filtering out troublesome characters, but the output would unpleasant.
While searching for a solution I ran into an implementation that came very close to fixing the issue, but still had minor misaligned text which was highly visible and distracting to me. Not being happy with the improperly aligned text I started doing some tinkering and testing various unicode characters for width. I was able to stumble onto an unobtrusive character that seems to be on most platforms AND (more importantly) is the equivalent to one pixel wide.
In addition to fixing the problem with misaligned text I was able to add the ability to ‘properly’ align numbers to the right (for those of us using left to right rendering fonts).
Tables of output for the SimbeyMod teleport feature:
The implementation allows for left, right, and center alignment for columns. In addition the behavior keeps the table only as wide as required for the widest display area needed and will collapse ‘less important’ information as required.
Dynamic sizing of the ‘Name’ Column:
Dynamic removal of ‘less important’ Column:
I ended up with following solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
package com.simbey.mod; //------------------------------------------------------------------------------ // ColText // // Aligns text in a minecraft chat. // // Inspired by (TabText.java v 5 by atesin#gmail,com). // import java.util.HashMap; import java.text.NumberFormat; import org.bukkit.Bukkit; import org.bukkit.ChatColor; class ColText { private static int max_chat_line_length = 51; private static String one_console = " "; private static String quad_console = " "; private static String one_visual = new String("\u205A"); private static String quad_visual = " "; private static String two = ".!,:;i|"; private static String three = "'`l"; private static String four = " I[]t"; private static String five = "\"()*<>fk{}"; private static String six = "ABCDEFGHJKLMNOPQRSTUVWXYZ01234567890abcdeghjmnopqrsuvwxyz#$%^&_+-=\\/><?"; private static String seven = "@~"; private static int ALIGN_LEFT = 1; private static int ALIGN_RIGHT = 2; private static int ALIGN_CENTER = 3; private static int ALIGN_END = 4; private Col[] columns; private boolean console = false; private String one_fill = one_visual; private String quad_fill = quad_visual; // Helper function during static init of the lookup map // private static void InitMap(HashMap<Character,Integer> m,String s,int i) { for(int x = 0;x < s.length();++x) { m.put( s.charAt(x), i); } } // Map of chars to "adjusted" widths. (Baseline width is 6 for a "wide" char) // private static HashMap<Character,Integer> countmap = new HashMap<Character,Integer>() {{ InitMap(this, two, 2); InitMap(this, three, 3); InitMap(this, four, 4); InitMap(this, five, 5); InitMap(this, six, 6); InitMap(this, seven, 7); }}; // Storage for each column of data // class Col { public String text; // Text for a header public Integer width; // Width based on "wide" chars public int align; // Alignment in the column public boolean hidden; Col(String s) { char a = s.charAt(0); if( a == '>' ) { // Right alignment // align = ALIGN_RIGHT; text = s.substring(1); } else if( a =='<' ) { // Left alignment // align = ALIGN_LEFT; text = s.substring(1); } else if ( a == '_' ) { // Center Alignment // align = ALIGN_CENTER; text = s.substring(1); } else { align = ALIGN_END; text = s; } width = ColText.calc_text_width(text,false); text = text.trim(); hidden = false; } }; // Adjustment factor for console/chat // private int Factor(int width) { if(console) { return width; } return width * 6; } // Calculates length without escapes // private static int calc_text_width(String s, boolean visual) { int width = 0; for(int i = 0; i < s.length(); ++i ) { char c = s.charAt(i); if( c == 167 ) // The minecraft "ChatColor" escape char { ++i; // The escaped value } else if(visual) { Integer wth = countmap.get(c); if( wth != null ) { width += wth; } } else { ++width; } } return width; } // This routine adds the string to the line clipping or padding // the length as required to assure that the value will fit within // the region given. // private void Pad(StringBuilder sb, String s, int pad_l, int pad_r) { String esc_b = ""; // Leading escapes stripped String esc_e = ""; // Trailing escapes stripped int b = 0; // Start of usable string int e = s.length(); // End of usable string int q_l = 0; // Quad parts to pad left int o_l = 0; // Single parts to pad left int q_r = 0; // Quad parts to pad right int o_r = 0; // Single parts to pad right // If the value overflows, we need to trim, but trimming could cause // the need to pad, so trim first, then pad again if required. // First any left padding (For right alignment or centering) // if( pad_l < 0 ) { for(int i = 0; i < e; ++i ) { char c = s.charAt(i); // Check for if( c == 167 ) // The minecraft "ChatColor" escape char { esc_b += s.substring( i, i + 2 ); ++i; // The escaped value } else { pad_l += calc_text_width( s.substring( i, i + 1 ), !console ); if( pad_l >= 0 ) { b = ++i; break; } } } } // Quad and Singles is mostly for the visual alignment // if( pad_l > 0 ) { q_l = pad_l/4; o_l = pad_l%4; } // Handle the right padding too // if( pad_r < 0 ) { for(int i = s.length() - 1 ; i > 0; --i) { if( i > 1 ) { if( s.charAt(i-1) == 167 ) { esc_e += s.substring( i-1, i+1 ); --i; } else { pad_r += calc_text_width( s.substring( i, i +1 ), !console ); if( pad_r >= 0 ) { e = i; break; } } } } } if( pad_r > 0 ) { q_r = pad_r/4; o_r = pad_r%4; } // Add any required left padding // for(int i = 0; i < q_l; ++i ) sb.append(quad_fill); if( o_l > 0 ) { sb.append(ChatColor.DARK_GRAY); for(int i = 0; i < o_l; ++i ) sb.append(one_fill); sb.append(ChatColor.RESET); } // Plus any stripped escape sequences // if(esc_b.length() > 0) { sb.append(esc_b); } // Now the parts of the string that will fit // sb.append(s.substring(b,e)); // Any stripped escape sequences.. // if(esc_e.length() > 0) { sb.append(esc_e); } // And any right padding // for(int i = 0; i < q_r; ++i ) sb.append(quad_fill); if(o_r > 0) { sb.append(ChatColor.DARK_GRAY); for(int i = 0; i < o_r; ++i ) sb.append(one_fill); sb.append(ChatColor.RESET); } // Plus the inter-column gap // sb.append(quad_fill); } private static int fixedWidthNumber(Long number) { return calc_text_width( Comma(number), false ); } // Constructor // ColText(String... def) { columns = new Col[def.length]; for(int i = 0; i < def.length; ++i ) { columns[i] = new Col(def[i]); } } // Setup for console or chat mode // public void SetConsoleMode(boolean value) { console = value; if(console) { one_fill = one_console; quad_fill = quad_console; } else { one_fill = one_visual; quad_fill = quad_visual; } } // Create a header composite string // public String Header() { String hdr[] = new String[columns.length]; for(int i = 0 ; i < columns.length; ++i ) { hdr[i] = new String( ChatColor.UNDERLINE + columns[i].text + ChatColor.RESET ); } return Row(hdr) + "\n "; } // Allow "less important" columns to be removed if the max length // will be exceeded. // public void OmitIfRequired(int...col) { int width = 0; for(Col c : columns) { if(!c.hidden) { width += c.width; } } if( width > max_chat_line_length ) { for(int i : col) { columns[i].hidden = true; } } } // Create a row composite string // public String Row(String...row_data) { assert( row_data.length == columns.length ); StringBuilder sb = new StringBuilder(100); for(int i = 0; i < row_data.length; ++i ) { Col c = columns[i]; if(!c.hidden) { int w = Factor(c.width); if( w > 0 ) { int visual_len = calc_text_width( row_data[i], !console ); int size_diff = w-visual_len; int pad_left = 0; int pad_right = 0; if( c.align == ALIGN_LEFT ) { pad_right = size_diff; } else if( c.align == ALIGN_RIGHT ) { pad_left = size_diff; } else if( c.align == ALIGN_CENTER ) { pad_left = pad_right = (size_diff/2); pad_right += (size_diff%2); } Pad( sb, row_data[i], pad_left, pad_right ); } else { sb.append( row_data[i] ); } } } return sb.toString(); } // Turn an integer into a more human friendly visual value // public static String Comma(long number) { return NumberFormat.getIntegerInstance().format(number); } public static String SelectNumberHeader(int number,String postfix,String...abrv) { return SelectNumberHeader((Long)(long)number,postfix,abrv); } public static String SelectNumberHeader(Long number,String postfix,String...abrv) { String h1 = ">"; int count_max_width = ColText.fixedWidthNumber(number) + postfix.length(); for(int i = 0; i < abrv.length-1; ++i ) { String abreviation = abrv[i]; if( count_max_width >= abreviation.length() ) { count_max_width -= (abreviation.length()-1); h1 += abreviation; break; } } if( h1.equals(">") ) { h1 += abrv[abrv.length-1]; count_max_width -= abrv[abrv.length-1].length() - 1; } for(int k = count_max_width; k > 1; --k ) { h1 = h1 + " "; } return h1; } }; |
Usage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
String HN = ColText.SelectNumberHeader(mapJumps.size(),".","Number","Num"); String HU = "<Name "; String HX = ColText.SelectNumberHeader(max_x,"", "X"); String HY = ColText.SelectNumberHeader(max_y,"", "Y"); String HZ = ColText.SelectNumberHeader(max_z,"", "Z"); String HC = ColText.SelectNumberHeader(max_c,"", "Energy Cost", "Cost"); // Trim the name column to the longest named item // if( max_n > 4 && (max_n < (HU.length()-1) ) ) { HU = HU.substring(0,max_n+1); } ColText cols = new ColText( HN, HU, HX, HY, HZ, HC ); // If the user likes long names or is "way out in the wild" // we aren't likely going to fit all of the text on a single line // so the less important columns can be removed. // cols.OmitIfRequired(3); cols.OmitIfRequired(0); cols.OmitIfRequired(2,4); // For each row send the string to the chat output: // String row = cols.Row( Comma(i), strName, X, Y, Z, C ); sender.sendMessage( row ); |
The “Hope Monkey” is dead, long live the “Hope Monkey” January 28, 2015 at 4:17 pm
I recently re-read the first book of the “Star Force” series Swarm by B.V. Larson. In that book the main character talks about how his “Hope Monkey” grabbed a hold of him various times in the book.
I just went through a similar emotional situation (thankfully NOTHING ~AT ALL~ like the events in the book, JUST the emotional reactions). I tried REALLY hard not to even consider giving into the hope and I failed miserably. In both regards. For that which I had hope, and for letting the hope give me energy. It is a massive come down. I went from feeling on top of the world, to another place entirely.
You never WANT to ‘give up all hope,’ and I ‘hope’ that the gross death of the last “Hope Monkey” can be cast asunder and a new one can take its place. I am old enough to know that I am a “passionate individual” and that is a sword that has two edges and is many times as dangerous to the wielder as it is to the obstacles my passions can help me overcome.
Don’t take any of the analogies to seriously. Followed beyond the mere surface likeness, would make them exceptionally scary.
OK, so back to that book. I would not say “Mr. Larson is the worlds best producer of great literature.” It is enough for me to say that I enjoy his work and my kindle account is loaded with a good percentage of his product. Swarm is one of the most memorable (and the first) of the series, but all have been enjoyable. IDK if it would appeal to you. My tastes are “fairly pedestrian” apparently.
Interesting (To me) July 6, 2014 at 2:10 pm
Looking through code recently written I noticed that I was using std::for_each where the new syntax of range based for would have sufficed.
Given how it was used, I don’t understand why I didn’t use the new syntax…
std::vector < int > vec;
for( int c : vec )
{
//...
}
vs…
std::vector < int > vec;
std::for_each( vec.begin(), vec.end(), [&]( int c )
{
//...
} );
The new range based for is much easier to understand in this case. As far as code generation, both are fairly close to identical in an optimized build. If a lambda expression is required either expression can be used (‘just’ call the lambda in the loop). The only real place the std::for_each ~should~ be used is likely when the range is a subrange. I have many times wondered why for_each didn’t have an overload like so:
std::for_each( vec, [&]( int c )
{
//...
} );
or…
using string_map = std::map < std::string, int >;
string_map items;
//..
auto es = items.equal_range( "E" );
std::for_each( es, [&]( string_map::value_type& v )
{
//...
} );
Without aliases (or auto) try typing in the second expression. The pair<...> returned by equal range as a raw type is exceptionally painful to type, let alone read.
In general I prefer simpler looking code over more complex. (Ever looked through the std:: headers? Yipes!) Often while reviewing code a few days after writing it, I will notice that I could have done things a little better. When I am in control of the project I am not afraid to refactor.
Grumble June 10, 2014 at 6:03 pm
I have had crummy “luck” with power supplies. (Better them, than some of the alternatives!) I was in the middle of using my “big boy” Linux box today (remotely via XWindows and SSH) and “things” just ground to a halt. (All my VM’s that had network mappings to various resources hung, and the host OS wasn’t happy either.)
Took me a while to track down that problem. I always favor local over remote for trouble (mainly because I didn’t want to trapse over to the room my Linux box was in). When I finally figured out the problem I had to pull apart a bunch of wiring to get at the box. Then I had to start diagnosing issues by pulling likely culprits out of the box. In the end by the time I figured out it was the PSU, Corsair tech support was gone for the day. Sigh. Even ~IF~ they honor the warranty (it is registered and under a year old) that means at LEAST a week without my (big) computer. The AX1200 seems to be discontinued these days and I loath wiring. That is one of the reasons when I built this beast that I picked the modular Corsair. MUCH easier to deal with cable routing. Looks like the replacement AX1200i doesn’t use the same connectors so even if I jaunt over to FRYS and pick up something local, I am likely to have a “fun time.” rewiring everything. (I don’t trust their web site, but they say the AX1200 or AX1200i isn’t available in store.)
I suppose there is ~something~ to say about the Macbook Pro Retina that leaves almost everything beyond user intervention. Over all I use that machine (at least as a front end) more than any other. (Typically with the lid down, external mouse and keyboard too.) If it wasn’t for the few times I need to pull it and work with the machine remotely, I would likely be happier with something like a powerful Intel NUC device “glued” behind my monitors. The specs are getting fairly decent. Some will even support two 30″ monitors via Displayport 1.2 multi-streaming.