I'm using Message Broker 8 and MQ 7. When I try to use a Mapping Node in my message flow I get a java.lang.RuntimeException.
Here is what the event viewer shows:
( BROKER8.default ) The map script generation for QName ''{practica}:CambioFecha'' has failed, with the following details: ''java.lang.RuntimeException: ''.
The generation of the map has failed.
Review and resolve the problems indicated in the message from the map generation.
The full exception stack is:
ExceptionList: ( ['MQROOT' : 0xe052600]
(0x01000000:Name):RecoverableException = (
(0x03000000:NameValue):File = 'F:\build\S000_P\src\DataFlowEngine\PluginInterface\ImbJniNode.cpp' (CHARACTER)
(0x03000000:NameValue):Line = 1170 (INTEGER)
(0x03000000:NameValue):Function = 'ImbJniNode::evaluate' (CHARACTER)
(0x03000000:NameValue):Type = 'ComIbmMSLMappingNode' (CHARACTER)
(0x03000000:NameValue):Name = 'practica/DATAGRAMA#FCMComposite_1_7' (CHARACTER)
(0x03000000:NameValue):Label = 'practica.DATAGRAMA.Cambio Formato Fecha' (CHARACTER)
(0x03000000:NameValue):Catalog = 'BIPmsgs' (CHARACTER)
(0x03000000:NameValue):Severity = 3 (INTEGER)
(0x03000000:NameValue):Number = 2230 (INTEGER)
(0x03000000:NameValue):Text = 'Caught exception and rethrowing' (CHARACTER)
(0x01000000:Name ):RecoverableException = (
(0x03000000:NameValue):File = 'MbErrorHandler.java' (CHARACTER)
(0x03000000:NameValue):Line = 146 (INTEGER)
(0x03000000:NameValue):Function = 'evaluate' (CHARACTER)
(0x03000000:NameValue):Type = '' (CHARACTER)
(0x03000000:NameValue):Name = '' (CHARACTER)
(0x03000000:NameValue):Label = '' (CHARACTER)
(0x03000000:NameValue):Catalog = 'BIPmsgs' (CHARACTER)
(0x03000000:NameValue):Severity = 3 (INTEGER)
(0x03000000:NameValue):Number = 3946 (INTEGER)
(0x03000000:NameValue):Text = 'Caught BrokerXCIStaticException' (CHARACTER)
(0x01000000:Name ):Insert = (
(0x03000000:NameValue):Type = 5 (INTEGER)
(0x03000000:NameValue):Text = '{practica}:CambioFecha' (CHARACTER)
)
(0x01000000:Name ):Insert = (
(0x03000000:NameValue):Type = 5 (INTEGER)
(0x03000000:NameValue):Text = 'java.lang.RuntimeException: ' (CHARACTER)
)
(0x01000000:Name ):RecoverableException = (
(0x03000000:NameValue):File = 'MbErrorHandler.java' (CHARACTER)
(0x03000000:NameValue):Line = 310 (INTEGER)
(0x03000000:NameValue):Function = 'throwableToMbException' (CHARACTER)
(0x03000000:NameValue):Type = '' (CHARACTER)
(0x03000000:NameValue):Name = '' (CHARACTER)
(0x03000000:NameValue):Label = '' (CHARACTER)
(0x03000000:NameValue):Catalog = 'BIPmsgs' (CHARACTER)
(0x03000000:NameValue):Severity = 3 (INTEGER)
(0x03000000:NameValue):Number = 3949 (INTEGER)
(0x03000000:NameValue):Text = 'Caught BrokerXCIStaticException' (CHARACTER)
(0x01000000:Name ):Insert = (
(0x03000000:NameValue):Type = 5 (INTEGER)
(0x03000000:NameValue):Text = 'java.lang.RuntimeException:
' (CHARACTER)
)
)
)
)
)
The entire message flow was working fine. So, I think it is not an error of the mapping node. Another detail, in others flows the mapping node doesn't work at all and gives the same error. I don't know what could be the problem. Maybe a JRE error?
Any idea?
Thanks!
Josué
This is most probably due to the large Java heap size on 64 bit machines, as all the references are 4 bytes larger. To make it work, you could simply run it on a 32 bit broker or try any of the following -
Use Xcompressedrefs (the explanation about it is here -
http://publib.boulder.ibm.com/infocenter/javasdk/v6r0/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.60%2Fdiag%2Funderstanding%2Fmm_compressed_references.html)
a) Execute the following command in the broker prompt
mqsichangeproperties --broker name-- -e --EG name-- -o
ComIbmJVMManager -n jvmSystemProperty -v \"-Xcompressedrefs\"
b) Verify that the JVM option is successfully applied
mqsireportproperties --broker name-- -e --EG name-- -o
ComIbmJVMManager -n jvmSystemProperty
The system should display -
-Xcompressedrefs
c) Restart the Execution Group
Increase the JVM memory, the default is 256MB
a) Execute the following command
mqsichangeproperties --broker name-- -e --EG name-- -o
ComIbmJVMManager -n jvmMaxHeapSize -v 536870912
b) Verify that the JVM option is successfully applied
mqsireportproperties --broker name-- -e --EG name-- -o
ComIbmJVMManager -n jvmMaxHeapSize
c) Restart the Execution Group
Hope this helps
Related
I developed IDE using eclipse EMF/RCP in that I Developed one editor using xtext,rcp and emf
Following is my grammar for that Section
// automatically generated by Xtext
grammar com.xyz.pmide.RoutingLineINI with org.eclipse.xtext.common.Terminals
import "platform:/resource/com.xyz.pmide.routingline.xtext.model/model/pmrouting.ecore"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore
IniRoutingLineProject:
{IniRoutingLineProject}
(iniRoutingConfig=IniRoutingConfiguration)?
;
IniRoutingConfiguration:
{IniRoutingConfiguration}
(iniRoutingSectConfig=IniRoutingLogicSection)
(iniLogMessageSectionConfig=IniLogMessageSet)?
(iniPreDefGroupSectionConfig=IniPreDefGroupVariableSet)?
(iniRegWSSectionConfig=IniRegisterWSCommandSet)?
(iniOtherRoutingSectionConfig=IniRoutingPropertySet)
(iniGlobalRoutingSectionConfig=IniGlobalRoutingSection)?
(iniAlarmSignalSectionConfig=IniAlarmSignalSection)?
(iniOptionPopupSectionConfig=IniOptionPopupSection)
;
IniRoutingLogicSection:
{IniRoutingLogicSection}
'[Routing]'('\r\n')*
// ('Warning_Rate='warningRate=ANS1TERM)?('\r\n')*
// ('Busy_Rate='busyRate=ANS1TERM)?('\r\n')*
// ('MaxRecursionConcurence=' maxRecursionOccurence=ANS1TERM)?('\r\n')*
// ('WS_Speed=' wsSpeed=ANS1TERM)?('\r\n')*
// ('ReactivationTime=' reactivationTime=ANS1TERM)?('\r\n')*
// ('WaitTime_WS_Reuse=' waitTimeWSReuse=ANS1TERM)?('\r\n')*
(routingLines+=IniRoutingLine)*('\r\n')*
;
terminal ALPHA :('a'..'z'|'A'..'Z');
terminal NUM:('0'..'9')+;
terminal SYMBOL : ('.'|','|'('|')'|'{'|'}'|'<'|'>'|'+'|'-'|'*'|'%'|'!'|'"'|':'|'|'|'?'|'#'|'_'|' '|'=');
terminal SYMBOL1 : ('['|']')*;
terminal SYMBOL2 : ('/'|';')* ;
terminal ANS : (ALPHA|NUM|SYMBOL)* SYMBOL2;
terminal SL_COMMENT : '//-' !('\n'|'\r')* ('\r'? '\n')?;
terminal ML_COMMENT : '//*' -> '*//';
ANSTERM : ANS;
ANSS1TERM : (ANS|SYMBOL1)+;
GRPCOMMENT_STR_END : SYMBOL2("===========================================================================================================================================================================") ;
GRPCOMMENT :
(GRPCOMMENT_STR_END)('\r\n')*
SYMBOL2(ANSS1TERM)('\r\n')*
(GRPCOMMENT_STR_END)('\r\n')*
;
LINECOMMENT :
// (LINECOMMENT_STR_END)('\r\n')*
// (ANSS1TERM|LINECOMMENT)('\r\n')*
// (LINECOMMENT_STR_END)?('\r\n')*;
(('/*'('\r\n')*
(ANSS1TERM)('\r\n')*
(LINECOMMENT)?('\r\n')*
'*/'?('\r\n')*)|GENCOMMENT)
;
IniTimeStampSampleSectPropSet:
{IniTimeStampSampleSectPropSet}
'[TimeStamp_Sample]'('\r\n')*
(inLabKeyValue+=IniUnitPositionsPair)*('\r\n')*
;
IniPositionConnect:
{IniPositionConnect}
// (srcPosition=ANS1TERM)(destPosition=ANS1TERM)?('\r\n')*
(src_dest_Pos=ANSS1TERM)('\r\n')*
;
IniListSampleSection:
{IniListSampleSection}
'[LISTSAMPLE]'('\r\n')*
(iniOnType+=IniListSample_OnType)*('\r\n')*
;
IniListSample_OnType:
{IniListSample_OnType}
(sampleType=('OnType'|ANSS1TERM))(popUpNo=ANSS1TERM)?('\r\n')*
;
IniGeneralRoutingSectPropSet:
{IniGeneralRoutingSectPropSet}
'[General]'('\r\n')*
// (version=('version='|ANSTERM))?('\r\n')*
(keySet+=IniNewKey_NL)*('\r\n')*
;
IniChildWSTriggerSectionSet:
{IniChildWSTriggerSectionSet}
(iniTriggerSectionConfig+=IniTriggerSectionConfiguration)*('\r\n')*
;
IniTriggerSectionConfiguration:
{IniTriggerSectionConfiguration}
SYMBOL1(sectName=ANSTERM)SYMBOL1('\r\n')*
(triggerUnit=('TriggerUnit='|ANSTERM))?('\r\n')*
(createPoint=('CreatePoint='|ANSTERM))?('\r\n')*
;
Following is my part validation or u can say check rules for my sections in editor
#Check
def validate_TriggerSectionConfiguration(IniTriggerSectionConfiguration iniTriggerSectionConfiguration){
val value = iniTriggerSectionConfiguration.sectName;
if (value.startsWith("[") && !value.endsWith("]")) {
error("Missing \"]\"",iniTriggerSectionConfiguration, PmroutingPackage.Literals.INI_TRIGGER_SECTION_CONFIGURATION__SECT_NAME)
}
}
Following is my part of editor
If I change above name by capital S
If I will go to red error mark this error message I am getting
I am trying to find solution I didn’t find. My problem is in checkRule
If I haven’t write any validation for that error why xtext giving such
error. This Problem I got when my name starts with this Capital
letters error A, G, L, M, O, P, R, S, T, W. Is this my code issue or
xtext has some bugs or I am missing something?
We have a number of Lanier MFPs that use the scan-to-folder option to allow people to get their documents, and we are starting to implement more security measures on the AD passwords they use by forcing a password reset.
Unfortunately, the Laniers use a proprietary encryption for the passwords. I've managed to get a functional Java command that will encrypt passwords into this format. The problem I've been encountering is that I then have to get this encoded password into PowerShell to pass it to the scanner.
I can run the Java command through a command line, but can't pass the encrypted password back into PowerShell as a string that the printer will accept (it needs to be in Base64). If I do pass the encoded password back into PowerShell, then run it through PowerShell's Base64 creation process, it is, obviously, changed too much for the scanner to use it.
What I need to determine is whether there's a way for me to take the following command line command, and get it to run in PowerShell, then provide me its output so I can pass this to the printer.
java -cp ./commons-codec-1.10.jar;. cdm.GwpwesCharacterEncoding %pass% "gwpwes002"
The Java command outputs a Base64 string based on the following line:
return new String(Base64.encodeBase64((byte[])encrypt));
As an example, if I pass the text 'Test' into that, I get the string "HVhcmtla25meHVncHQ=="
This is useless to me, though, as I can't then get this back into PowerShell to pass through to the printer, and if I encode it as Base64 with PowerShell, it comes out as "MgBoAHMAWgBtADkAegBjADIAQgBxAGUAMABKAHgAWgBYAGgAbgBiAG0AMAB3AD0A".
Can anyone help?
Revised code after some assistance:
$pass1 = "test"
$path = "c:\Test\printercreds"
$encode = "gwpwes002"
cd $path
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pInfo.FileName = 'java'
$pInfo.Arguments = "-jar .\commons-codec-1.10.jar cdm.GwpwesCharacterEncoding $pass1 $encode"
$pInfo.UseShellExecute = $false
$pInfo.RedirectStandardOutput = $true
$pInfo.RedirectStandardError = $true
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $pInfo
[void]$process.Start()
$passsec = $process.StandardOutput.ReadtoEnd()
$process.WaitforExit()
write-host $passsec
Please try this. Its the encoding for GWPWES002. I found a old java version here.
https://www.dropbox.com/s/3324g84x0l4bnon/GwpwesCharacterEncoding.java?dl=0
There is a weakness in this "encoding". The front part of the encoding is just random padding. the pack part is where the actual string is stored. Running the script on the same string just a few times points out this error.
encodeGwpwes002 -code "a"
generated this hashes
np6eWFieWJ6eWA==
np6eWJ5YWFieWA==
WFienlhYnlieWA==
nlhYnp5Ynp6eWA==
nlieWFieWJ6eWA==
everything up until eWA== is just random padding mean "eWA==" == "a"
same for "aaaaaaaa"
np5YWJ5YnlieWFhYWFhYWFg=
np5Ynp6eWJ6eWFhYWFhYWFg=
nlienp6eWJ6eWFhYWFhYWFg=
WJ5YWJ6enlieWFhYWFhYWFg=
Meaning that
"eWFhYWFhYWFg=" Is "aaaaaaaa".
the password you provided as "test", A example of manipulation would be :
HVhcmtla25meHVncHQ== IS "test" :: 29 88 92 154 217 90 219 153 158 29 89 220 29
HVhcmtla25meFVncHQ== IS "Test" :: 29 88 92 154 217 90 219 153 158 21 89 220 29
Here is the powershell I have translated below
#private static String encodeGwpwes002(String code, int codeSize) {
function encodeGwpwes002([string]$code, [int]$codeSize = 0){
#byte[] protectCode;
[byte]$protectCode | Out-Null
#try {
try{
#protectCode = code.getBytes("UTF-8");
$protectCode = [System.Text.Encoding]::UTF8.GetBytes($code)
#}catch (Throwable e) {
}catch{
#return null;
return $null
#}
}
#int encodeSize = codeSize;
[int]$encodeSize = $codeSize
#if (protectCode.length >= codeSize) {
if(($protectCode.length) -ge $codeSize){
#encodeSize = protectCode.length + 9;
$encodeSize = ($protectCode.length) + 9
#}
}
#byte[] simple = new byte[encodeSize];
[byte[]]$simple = New-Object byte[] $encodeSize
#int diffuseCnt = 0;
[int]$diffuseCnt = 0
#int simpleCnt = 0;
[int]$simpleCnt = 0
#if (protectCode.length < encodeSize - 1) {
if(($protectCode.length) -lt ($encodeSize - 1)){
#for (diffuseCnt = 0; diffuseCnt < encodeSize - 1 - protectCode.length; ++diffuseCnt) {
for($diffuseCnt = 0; $diffuseCnt -lt ($encodeSize - 1 - ($protectCode.length)); $diffuseCnt++){
#simple[diffuseCnt] = (byte)(Math.random() * 25.0 + 97.0);
$simple[$diffuseCnt] = [byte] (Get-Random -Maximum 0.9 -Minimum 0.1) * 25.0 + 97.0
#}
}
#}
}
#simple[diffuseCnt++] = 122;
$simple[$diffuseCnt++] = 122
#for (simpleCnt = diffuseCnt; simpleCnt < protectCode.length + diffuseCnt; ++simpleCnt) {
for($simpleCnt = $diffuseCnt; $simpleCnt -lt ($protectCode.length) + $diffuseCnt; $simpleCnt++){
#simple[simpleCnt] = protectCode[simpleCnt - diffuseCnt];
$simple[$simpleCnt] = $protectCode[$simpleCnt - $diffuseCnt];
#}
}
#byte[] encrypt = new byte[simpleCnt];
[byte[]] $encrypt = New-Object byte[] $simpleCnt
#for (int i = 0; i < simpleCnt; ++i) {
for([int]$i=0; $i -lt $simpleCnt; $i++) {
#byte work = 0;
[byte]$work = 0
#work = (byte)((simple[i] & 192) >>> 6 | (simple[i] & 63) << 2);
$work = [byte](($simple[$i] -band 192) -shr 6 -bor ($simple[$i] -band 63) -shl 2)
#encrypt[i] = (byte)((work & 240) >>> 4 | (work & 15) << 4);
$encrypt[$i] = [byte](($work -band 240) -shr 4 -bor ($work -band 15) -shl 4)
#}
}
#return new String(Base64.encodeBase64((byte[])encrypt));
return [string]([System.Convert]::ToBase64String([byte[]]$encrypt))
#}
}
encodeGwpwes002TEST -code "Test"
$startCount = 5;
$processors = Get-WmiObject -Class Win32_ComputerSystem | select -
ExpandProperty "NumberOfLogicalProcessors";
$perInstance = $processors / $startCount;
$affinityloop = 1;
$affinityvalue = 0;
for($i=1; $i -le $startCount; $i++) {
$affinityvalue = 0;
for($u=1; $u -le $perInstance ; $u++) {
$affinityvalue = $affinityvalue + $affinityloop;
$affinityloop = $affinityloop * 2;
}
$ps = new-object System.Diagnostics.Process;
$ps.StartInfo.Filename = "C:\jdk\bin\java.exe";
$ps.StartInfo.Arguments = " -server -Xms10240m -Xmx10240m -XX:+UseG1GC -cp `".;*`" Worker";
$ps.start();
Write-Host $affinityvalue ;
$ps.ProcessorAffinity = [Convert]::ToString($affinityvalue, 16);
}
I am trying to start a Windows Java application on two different NUMA nodes. Has anyone able to accomplish this with Diagnostics.Process format? This code does work fine, but all applications created are on the same NUMA node and hence only using 50% power.
I tried codes such as $mod = ($i % 2); to help prepare for some way to alternate the NUMA node but unsure how to specify it within the script.
EDIT
Tried to load balance with ProcessorAffinity and I get crashes due to Double unable to convert to IntPtr
EDIT 2
So it looks like Windows Groups the processors past 64 into Groups. Can't seem to find a way to alter that like ProcessAffinity. I guess its just not that common. You can easily do it in Task manager, just need to find a way to do it in Powershell or similar.
Suppose In my LDT(LargeMap) Bin I have following values,
key1, value1
key2, value2
key3, value3
key4, value4
. .
key50, value50
Now, I get my required data using following snippet :
Map<?, ?> myFinalRecord = new HashMap<?, ?>();
// First call to client to get the largeMap associated with the bin
LargeMap largeMap = myDemoClient.getLargeMap(myPolicy, myKey, myLDTBinName, null);
for (String myLDTKey : myRequiredKeysFromLDTBin) {
try {
// Here each get call results in one call to aerospike
myFinalRecord.putAll(largeMap.get(Value.get(myLDTKey)));
} catch (Exception e) {
log.warn("Key does not exist in LDT Bin");
}
}
The problem is here if myRequiredKeysFromLDTBin contains say 20 keys. Then largeMap.get(Value.get(myLDTKey)) will make 20 calls to aerospike.
Thus if I go by retrieval time of 1 ms per transaction , here my one call to retrieve 20 ids from a record will result in 20 calls to aerospike. This will increase my response time to approx. 20 ms !
So is there any way where I can just pass a set of ids to be retrieved from a LDT Bin and it takes only one call to do so ?
There is no direct API to do multi-get. A way of doing this would be call lmap API directly from server multiple time through UDF.
Example 'mymap.lua'
local lmap = require('ldt/lib_lmap');
function getmany(rec, binname, keys)
local resultmap = map()
local keycount = #keys
for i = 1,keycount,1 do
local rc = lmap.exists(rec, binname, keys[i])
if (rc == 1) then
resultmap[keys[i]] = lmap.get(rec, binname, keys[i]);
else
resultmap[keys[i]] = nil;
end
end
return resultmap;
end
Register this lua file
aql> register module 'mymap.lua'
OK, 1 module added.
aql> execute lmap.put('bin', 'c', 'd') on test.demo where PK='1'
+-----+
| put |
+-----+
| 0 |
+-----+
1 row in set (0.000 secs)
aql> execute lmap.put('bin', 'b', 'c') on test.demo where PK='1'
+-----+
| put |
+-----+
| 0 |
+-----+
1 row in set (0.001 secs)
aql> execute mymap.getmany('bin', 'JSON["b","a"]') on test.demo where PK='1'
+--------------------------+
| getmany |
+--------------------------+
| {"a":NIL, "b":{"b":"c"}} |
+--------------------------+
1 row in set (0.000 secs)
aql> execute mymap.getmany('bin', 'JSON["b","c"]') on test.demo where PK='1'
+--------------------------------+
| getmany |
+--------------------------------+
| {"b":{"b":"c"}, "c":{"c":"d"}} |
+--------------------------------+
1 row in set (0.000 secs)
Java Code to invoke this would be
try {
resultmap = myClient.execute(myPolicy, myKey, 'mymap', 'getmany', Value.get(myLDTBinName), Value.getAsList(myRequiredKeysFromLDTBin)
} catch (Exception e) {
log.warn("One of the key does not exist in LDT bin");
}
Value will be set if key exists and it would return NIL if it does not.
Consider the following regular expression :
^[:;][-^]\)$
List all the strings that exactly match this expression or, if there are more than ten such strings, describe them.
Assuming the close paren is spurious, here is a slick solution:
% echo {':',';'}{'-','^'}\)
:-) :^) ;-) ;^)
Which is of course:
% perl -le 'print for <{:,;}{-,^})>'
:-)
:^)
;-)
;^)
Isn’t that cool?
And then of course, there's this:
#!/usr/bin/perl
use 5.010 ;
$stdout = 124.102.109.116;
open
stdout ;
use less
${"\42"} = "\54" ;
say
for
#224 =
eval
join
/\/\/\/∖/ =>
map
{"<$_>"}
join
/\/\/\/∖/ =>
map
{"{#$_}" }
[qw{ | [ } ] =>
[qw{ : ; % # } ] =>
[qw{ ^ = * _ ~ } ] =>
[qw{ / v ) | o 3 I } ]
which delightfully produces this:
|:^/ |:^v |:^) |:^| |:^o |:^3 |:^I |:=/ |:=v |:=) |:=| |:=o |:=3
|:=I |:_/ |:_v |:_) |:_| |:_o |:_3 |:_I |:~/ |:~v |:~) |:~| |:~o
|:~3 |:~I |;^/ |;^v |;^) |;^| |;^o |;^3 |;^I |;=/ |;=v |;=) |;=|
|;=o |;=3 |;=I |;_/ |;_v |;_) |;_| |;_o |;_3 |;_I |;~/ |;~v |;~)
|;~| |;~o |;~3 |;~I |%^/ |%^v |%^) |%^| |%^o |%^3 |%^I |%=/ |%=v
|%=) |%=| |%=o |%=3 |%=I |%_/ |%_v |%_) |%_| |%_o |%_3 |%_I |%~/
|%~v |%~) |%~| |%~o |%~3 |%~I |#^/ |#^v |#^) |#^| |#^o |#^3 |#^I
|#=/ |#=v |#=) |#=| |#=o |#=3 |#=I |#_/ |#_v |#_) |#_| |#_o |#_3
|#_I |#~/ |#~v |#~) |#~| |#~o |#~3 |#~I [:^/ [:^v [:^) [:^| [:^o
[:^3 [:^I [:=/ [:=v [:=) [:=| [:=o [:=3 [:=I [:_/ [:_v [:_) [:_|
[:_o [:_3 [:_I [:~/ [:~v [:~) [:~| [:~o [:~3 [:~I [;^/ [;^v [;^)
[;^| [;^o [;^3 [;^I [;=/ [;=v [;=) [;=| [;=o [;=3 [;=I [;_/ [;_v
[;_) [;_| [;_o [;_3 [;_I [;~/ [;~v [;~) [;~| [;~o [;~3 [;~I [%^/
[%^v [%^) [%^| [%^o [%^3 [%^I [%=/ [%=v [%=) [%=| [%=o [%=3 [%=I
[%_/ [%_v [%_) [%_| [%_o [%_3 [%_I [%~/ [%~v [%~) [%~| [%~o [%~3
[%~I [#^/ [#^v [#^) [#^| [#^o [#^3 [#^I [#=/ [#=v [#=) [#=| [#=o
[#=3 [#=I [#_/ [#_v [#_) [#_| [#_o [#_3 [#_I [#~/ [#~v [#~) [#~|
[#~o [#~3 [#~I