	}
}

//! draws the element and its children
void CGUIComboBox::draw()
{
	if (!IsVisible)
		return;

	IGUISkin *skin = Environment->getSkin();

	updateListButtonWidth(skin->getSize(EGDS_SCROLLBAR_SIZE));

	// font changed while the listbox is open?
	if (ActiveFont != skin->getFont() && ListBox) {
		// close and re-open to use new font-size
		openCloseMenu();
		openCloseMenu();
	}

	IGUIElement *currentFocus = Environment->getFocus();
	if (currentFocus != LastFocus) {
		HasFocus = currentFocus == this || isMyChild(currentFocus);
		LastFocus = currentFocus;
	}

	// set colors each time as skin-colors can be changed
	SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
	if (isEnabled()) {
		SelectedText->setDrawBackground(HasFocus);
		SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
	} else {
		SelectedText->setDrawBackground(false);
		SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
	}
	ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
	ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));

	core::rect<s32> frameRect(AbsoluteRect);

	// draw the border

	skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
			true, true, frameRect, &AbsoluteClippingRect);

	// draw children
	IGUIElement::draw();
}

void CGUIComboBox::openCloseMenu()
{
	if (ListBox) {
		// close list box
		Environment->setFocus(this);
		ListBox->remove();
		ListBox = nullptr;
	} else {
		if (Parent) {
			SEvent event;
			event.EventType = EET_GUI_EVENT;
			event.GUIEvent.Caller = this;
			event.GUIEvent.Element = nullptr;
			event.GUIEvent.EventType = EGET_LISTBOX_OPENED;

			// Allow to prevent the listbox from opening.
			if (Parent->OnEvent(event))
				return;

			Parent->bringToFront(this);
		}

		IGUISkin *skin = Environment->getSkin();
		u32 h = Items.size();

		if (h > getMaxSelectionRows())
			h = getMaxSelectionRows();
		if (h == 0)
			h = 1;

		ActiveFont = skin->getFont();
		if (ActiveFont)
			h *= (ActiveFont->getDimension(L"A").Height + 4);

		// open list box
		core::rect<s32> r(0, AbsoluteRect.getHeight(),
				AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);

		ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
		ListBox->setSubElement(true);
		ListBox->setNotClipped(true);
		ListBox->drop();

		// ensure that list box is always completely visible
		if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
			ListBox->setRelativePosition(core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0));

		for (s32 i = 0; i < (s32)Items.size(); ++i)
			List


73, 7},
  ['haste']                     = {101, 6},
  ['ultimatehealingrune']       = {62, 5},
  ['intensehealingrune']        = {74, 4},
  ['ultimatehealing']           = {1, 3},
  ['intensehealing']            = {7, 2},
  ['lighthealing']              = {6, 1},
}

VocationNames = {
  [1] = 'Sorcerer',
  [2] = 'Druid',
  [3] = 'Paladin',
  [4] = 'Knight',
  [5] = 'Master Sorcerer',
  [6] = 'Elder Druid',
  [7] = 'Royal Paladin',
  [8] = 'Elite Knight'
}

SpellGroups = {
  [1] = 'Attack',
  [2] = 'Healing',
  [3] = 'Support',
  [4] = 'Special',
  [5] = 'Cripple'
}

Spells = {}

function Spells.getClientId(spellName)
  local profile = Spells.getSpellProfileByName(spellName)

  local id = SpellInfo[profile][spellName].icon
  if not tonumber(id) and SpellIcons[id] then
    return SpellIcons[id][1]
  end
  return tonumber(id)
end

function Spells.getServerId(spellName)
  local profile = Spells.getSpellProfileByName(spellName)

  local id = SpellInfo[profile][spellName].icon
  if not tonumber(id) and SpellIcons[id] then
    return SpellIcons[id][2]
  end
  return tonumber(id)
end

function Spells.getSpellByName(name)
  return SpellInfo[Spells.getSpellProfileByName(name)][name]
end

function Spells.getSpellByWords(words)
  local words = words:lower():trim()
  for profile,data in pairs(SpellInfo) do
    for k,spell in pairs(data) do
      if spell.words == words then
        return spell, profile, k
      end
    end
  end
  return nil
end

function Spells.getSpellByIcon(iconId)
  for profile,data in pairs(SpellInfo) do
    for k,spell in pairs(data) do
      if spell.id == iconId then
        return spell, profile, k
      end
    end
  end
  return nil
end

function Spells.getSpellIconIds()
  local ids = {}
  for profile,data in pa


each prior Mine in Detonation Sequence"}}},name="additional_proj_per_mine_in_sequence",stats={[1]="display_additional_projectile_per_mine_in_detonation_sequence"}},[502]={lang={English={[1]={[1]={k="negate",v=1},[2]={k="reminderstring",v="ReminderTextDamageTypes"},limit={[1]={[1]="#",[2]="#"}},text="100%% of Physical Damage Converted to other Damage Types matching the Brand Gem's Tags"}}},name="display_brand_deonate_tag_conversion",stats={[1]="display_brand_deonate_tag_conversion"}},[503]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="Applied Curses have %1%%% increased Effect"},[2]={[1]={k="negate",v=1},limit={[1]={[1]="#",[2]=-1}},text="Applied Curses have %1%%% reduced Effect"}}},name="linked_curse_effect_incr",stats={[1]="display_linked_curse_effect_+%"}},[504]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Debuff can have up to %1% layers of Damage"}}},name="blight_max_stacks",stats={[1]="display_max_blight_stacks"}},[505]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Burning Debuff can have a maximum of %1% stages"}}},name="fire_beam_max_stacks",stats={[1]="display_max_fire_beam_stacks"}},[506]={lang={English={[1]={limit={[1]={[1]=1,[2]="#"}},text="First Mine Detonates Instantly\nMines get %1%%% more Detonation Speed for each prior Mine in Detonation Sequence"},[2]={[1]={k="negate",v=1},limit={[1]={[1]=1,[2]="#"}},text="First Mine Detonates Instantly\nMines get %1%%% less Detonation Speed for each prior Mine in Detonation Sequence"}}},name="mine_detonation_sequence_speed_incr",stats={[1]="display_mine_deontation_mechanics_detonation_speed_+%_final_per_sequence_mine"}},[507]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Strike Skills used by Mirage Saviours cannot target additional Enemies"}}},name="display_mirage_warriors_no_spirit_strikes",stats={[1]="display_mirage_warriors_no_spirit_strikes"}},[508]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Modifiers to Melee Strike Range also apply to this Skill's Area radius"}}},name="display_melee_range_applies_to_radius",stats={[1]="display_modifiers_to_melee_attack_range_apply_to_skill_radius"}},[509]={lang={English={[1]={[1]={k="reminderstring",v="ReminderTextElusive"},limit={[1]={[1]=1,[2]=1}},text="Removes existing Elusive before granting a new Elusive Buff when used"}}},name="elusive_swap_on_use",stats={[1]="display_removes_and_grants_elusive_when_used"}},[510]={lang={English={[1]={limit={[1]={[1]="#",[2]="#"}},text="Buff expiry rate cannot be modified"}}},name="display_fixed_duration_buff",stats={[1]="display_skill_fixed_duration_buff"}},[511]={lang={English={[1]={[1]={k="milliseconds


/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2005 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: md5global.h,v 1.1.1.1 2005/03/18 20:17:28 zautrix Exp $
 */

/* GLOBAL.H - RSAREF types and constants
 */

#ifndef MD5GLOBAL_H
#define MD5GLOBAL_H

namespace md5
{

	/* PROTOTYPES should be set to one if and only if the compiler supports
	function argument prototyping.
	The following makes PROTOTYPES default to 0 if it has not already
	been defined with C compiler flags.
	*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif

	/* POINTER defines a generic pointer type */
	typedef unsigned char *POINTER;

	/* UINT2 defines a two byte word */
	typedef unsigned short int UINT2;

	/* UINT4 defines a four byte word */
	//typedef unsigned long int UINT4;
	typedef unsigned int UINT4;

	/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
	If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
	returns an empty list.
	*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif

}

#endif


ng[0].lower() == "first":
                        temp_semester_format = f"1/{str(temp_mapping[2])}"
                    elif temp_mapping[0].lower() == "second":
                        temp_semester_format = f"2/{str(temp_mapping[2])}"
                    elif temp_mapping[0].lower() == "summer":
                        temp_semester_format = f"summer/{str(temp_mapping[2])}"
                    temp_semester['semester'] = temp_semester_format
                    foundSemester = True
                elif foundSemester:
                    if item[0] is None or item[1] == None or item[2] == None or item[3] == None:
                        continue
                    temp_course['courseID'] = item[0]
                    temp_course['courseName'] = item[1]
                    temp_course['grade'] = item[2]
                    temp_course['credit'] = item[3]
                    temp_semester['courses'].append(temp_course)
                    # clear value
                    temp_course = temp_course.fromkeys(temp_course, None)

    return {
        "studentId" : student_id,
        "thaiName" : student_thai_name,
        "result" : result,
    }


  Person[]
         } as
         @com.orbitalhq.formats.Csv(
                     delimiter = "|",
                     nullValue = "NULL"
                  )
         {
              firstName: FirstName
              age: Age
         }[]
      """.trimIndent()
      val taxiQl = Compiler(source = vyneQlQuery, importSources = listOf(schema.taxi)).queries().first()
      val vyneAnonymousType =  ProjectionAnonymousTypeProvider.toVyneAnonymousType(
         taxiQl.projectedType!!,
         schema
      )

      val results = """[
         |{ "firstName" : "Jimmy" , "age" : 50 },
         |{ "firstName" : "Peter" , "age" : 50 } ]"""
         .trimMargin()
      val typedCollection = TypedInstance.from(vyneAnonymousType, results, schema = schema, source = Provided) as TypedCollection
      this@QueryHistoryExporterTest.schemaProvider = schemaProvider
      prepareQueryHistoryResults(
         typedCollection,
         QuerySummary(
            queryId = "123",
            clientQueryId =  UUID.randomUUID().toString(),
            taxiQl = vyneQlQuery,
            queryJson = null,
            startTime = Instant.now(),
            responseStatus = QueryResponse.ResponseStatus.COMPLETED,
            anonymousTypesJson = objectMapper.writeValueAsString(setOf(vyneAnonymousType.collectionType))
         )
      )
      queryExporter.export(queryId = "123", exportFormat = ExportFormat.CUSTOM)
         .test {
            awaitItem().trim().should.equal(
               "firstName|age\r\n" +
                  "Jimmy|50")
            awaitItem().trim().should.equal("Peter|50")
            awaitComplete()
         }
   }

   private fun prepareQueryHistoryResults(results: String) {
      val (schemaProvider, schema) = SimpleTaxiSchemaProvider.from(
         """
         @com.orbitalhq.formats.Csv(
            delimiter = "|",
            nullValue = "NULL",
            useFieldNamesAsColumnNames = true
         )
         model Person {
            firstName : String
            lastName : String
            age : Int
         }
      """
      )
      this.schemaProvider = schemaProvider

      val typedInstance = TypedInstance.from(
         schema.type("Person[]"), results, schema = schema, source = Provided
      ) as TypedCollection
      prepareQueryHistoryResults(typedInstance)
   }

   private fun prepareQueryHistoryResults(typedInstance: TypedCollection, querySummary: QuerySummary = mock()) {
      val queryResults: List<QueryResultRow> = typedInstance.map { it.toTypeNamedInstance() }
         .map { QueryResultRow(queryId = "", json = objectMapper.writeValueAsString(it), valueHash = 123) }

      resultRowRepository = mock {
         on { findAllByQueryId(any()) } doReturn queryResults
      }
      historyRecordRepository = mock {
         on { findByQueryId(any()) } doReturn querySummary
      }
      queryExporter = QueryHistoryExporter(objectMapper, resultRowRepository, historyRecordRepository, schemaProvider, VyneQueryServiceExceptionProvider(), listOf(
          CsvFormatSpec
      ))
   }
}
// In order to make these tests easier, they depend on classes in
// schema-server.  However, that project is wired as a spring-boot runnable
// jar, so cannot be used as a dependency in other projects.
// The solution is to move some classes around.
// We ultimately plan on splitting the schema-server-runtime and schema-server-library,
// so that the server can be embedded.
// That will give these tests a library they can depend on, which will make
// them work.
// But,


hodCall);
            var model = MongoDBHelper.GetCollectionModelName(instrumentedMethodCall.MethodCall);
            var segment = transaction.StartDatastoreSegment(instrumentedMethodCall.MethodCall, new ParsedSqlStatement(DatastoreVendor.MongoDB, model, operation));

            return Delegates.GetDelegateFor(segment);
        }

        private string GetRemoveOperationName(MethodCall methodCall)
        {
            try
            {
                var removeFlags = ((RemoveFlags)methodCall.MethodArguments[1]);
                if (methodCall.MethodArguments[0] == null &&
                    removeFlags == RemoveFlags.None)
                    return "RemoveAll";
            }
            catch (Exception e)
            {
                throw new Exception("Expected a MongoDB.Driver.RemoveFlags as the second method argument.", e);
            }

            return "Remove";
        }
    }
}


z-0.5+d1+0.5D);
			if(!this.entity.world.collidesWithAnyBlock(aabb1)&&northWestPassable!=null&&!northWestPassable.visited&&northWestPassable.distanceTo(targetPoint) < maxDistance)
				pathOptions[optionCount++] = northWestPassable;
		}

		if(northPassable&&eastPassable)
		{
			PathPoint northEastPassable = this.getSafePoint(currentPoint.x+1, currentPoint.y, currentPoint.z-1, step, floor, EnumFacing.NORTH);
			double d1 = this.entity.width/2.0D;
			AxisAlignedBB aabb1 = new AxisAlignedBB(currentPoint.x+0.5-d1+0.5D, currentPoint.y+1.001D, currentPoint.z-0.5-d1+0.5D, currentPoint.x+0.5+d1+0.5D, ((float)currentPoint.y+1+this.entity.height), currentPoint.z-0.5+d1+0.5D);
			if(!this.entity.world.collidesWithAnyBlock(aabb1)&&northEastPassable!=null&&!northEastPassable.visited&&northEastPassable.distanceTo(targetPoint) < maxDistance)
				pathOptions[optionCount++] = northEastPassable;
		}

		if(southPassable&&westPassable)
		{
			PathPoint southWestPassable = this.getSafePoint(currentPoint.x-1, currentPoint.y, currentPoint.z+1, step, floor, EnumFacing.SOUTH);

			double d1 = this.entity.width/2.0D;
			AxisAlignedBB aabb1 = new AxisAlignedBB(currentPoint.x-0.5-d1+0.5D, currentPoint.y+1.001D, currentPoint.z+0.5-d1+0.5D, currentPoint.x-0.5+d1+0.5D, ((float)currentPoint.y+1+this.entity.height), currentPoint.z+0.5+d1+0.5D);
			if(!this.entity.world.collidesWithAnyBlock(aabb1)&&southWestPassable!=null&&!southWestPassable.visited&&southWestPassable.distanceTo(targetPoint) < maxDistance)
				pathOptions[optionCount++] = southWestPassable;
		}

		if(southPassable&&eastPassable)
		{
			PathPoint southEastPassable = this.getSafePoint(currentPoint.x+1, currentPoint.y, currentPoint.z+1, step, floor, EnumFacing.SOUTH);
			double d1 = this.entity.width/2.0D;
			AxisAlignedBB aabb1 = new AxisAlignedBB(currentPoint.x+0.5-d1+0.5D, currentPoint.y+1.001D, currentPoint.z+0.5-d1+0.5D, currentPoint.x+0.5+d1+0.5D, ((float)currentPoint.y+1+this.entity.height), currentPoint.z+0.5+d1+0.5D);
			if(!this.entity.world.collidesWithAnyBlock(aabb1)&&southEastPassable!=null&&!southEastPassable.visited&&southEastPassable.distanceTo(targetPoint) < maxDistance)
				pathOptions[optionCount++] = southEastPassable;
		}
		return optionCount;
	}

	@Nullable
	private PathPoint getSafePoint(int x, int y, int z, int p_186332_4_, double p_186332_5_, EnumFacing facing)
	{
		PathPoint point = null;
		BlockPos pos = new BlockPos(x, y, z);
		BlockPos below = pos.down();
		double d0 = y-(1.0D-this.blockaccess.getBlockState(below).getBoundingBox(this.blockaccess, below).maxY);
		if(d0-p_186332_5_ > 1.125D)
			return null;
		else
		{
			this.breakableFlag = false;
			PathNodeType type = this.getPathNodeType(this.entity, x, y, z);
			float priority = this.entity.getPathPriority


or]. The
		 *   [keys][A_Map.keysAsSet] constitute this type's complete
		 *   [ancestry][SetDescriptor] of Java types.
		 * @return
		 *   The requested pojo type.
		 */
		fun createFusedPojoType(javaAncestors: A_Map?): AvailObject =
			mutable.createImmutable {
				setSlot(HASH_OR_ZERO, 0)
				setSlot(JAVA_ANCESTORS, javaAncestors!!)
				setSlot(TYPE_VARIABLES, nil)
				setSlot(SELF_TYPE, nil)
			}
	}
}
/*
 * AtomWithPropertiesSharedDescriptor.kt
 * Copyright © 1993-2022, The Avail Foundation, LLC.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of the contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package avail.descriptor.atoms

import avail.AvailRuntimeSupport
import avail.annotations.HideFieldInDebugger
import avail.compiler.splitter.MessageSplitter
import avail.descriptor.atoms.A_Atom.Companion.getAtomProperty
import avail.descriptor.atoms.AtomDescriptor.SpecialAtom.EXPLICIT_SUBCLASSING_KEY
import avail.descriptor.atoms.AtomDescriptor.SpecialAtom.HERITABLE_KEY
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.IntegerSlots.Companion.HASH_OR_ZERO
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.IntegerSlots.HASH_AND_MORE
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.ObjectSlots.BUNDLE_OR_NIL
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.ObjectSlots.ISSUING_MODULE
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.ObjectSlots.NAME
import avail.descriptor.atoms.AtomWithPropertiesSharedDescriptor.ObjectSlots.PROPERTY_MAP_POJO
import avail.descriptor.bundles.A_Bundle
import avail.descriptor.bundles.MessageBundleDescriptor.Companion.newBundle
import avail.descriptor.methods.A_Method
import avail.descriptor.methods.MethodDescriptor.Companion.newMethod
import avail.descriptor.module.A_Module
import avail.descriptor.module.ModuleDescriptor
import avail.descriptor.pojos.RawPojoDescriptor
import avail.descriptor.pojos.RawPojoDescriptor.Companion.


', ':tab Gdiffsplit<Space>')
vim.keymap.set('n', ',dt', ':Git difftool -y<Space>')
vim.keymap.set('n', ',c', ':Git commit -v<CR>')
vim.keymap.set('n', ',C', ':Git commit --amend -v<CR>')
vim.keymap.set('n', ',e', '<Cmd>Gedit<CR>')
vim.keymap.set('n', ',r', '<Cmd>Gread<CR>')
vim.keymap.set('n', ',w', '<Cmd>Gwrite<CR>')
vim.keymap.set('n', ',b', '<Cmd>Git blame -w<Bar>wincmd p<CR>')
vim.keymap.set({ 'n', 'x' }, ',B', ':GBrowse')

vim.keymap.set('n', ',,', '<Cmd>diffget //2<CR>')
vim.keymap.set('n', ',.', '<Cmd>diffget //3<CR>')


  $w,
                    concat!("{:#width$", $ty, "}"),
                    $data,
                    width = $width as usize
                )
            }
        } else if $flags.contains(Flags::PREPEND_ZERO) {
            write!(
                $w,
                concat!("{:0width$", $ty, "}"),
                $data,
                width = $width as usize
            )
        } else {
            write!(
                $w,
                concat!("{:width$", $ty, "}"),
                $data,
                width = $width as usize
            )
        }
    }};
}

/// Write to a struct that implements [`fmt::Write`].
///
/// # Differences
///
/// There are a few differences from standard printf format:
///
/// - only valid UTF-8 data can be printed.
/// - an `X` format specifier with a `#` flag prints the hex data in uppercase,
///   but the leading `0x` is still lowercase
/// - an `o` format specifier with a `#` flag precedes the number with an `o`
///   instead of `0`
/// - `g`/`G` (shorted floating point) is aliased to `f`/`F`` (decimal floating
///   point)
/// - same for `a`/`A` (hex floating point)
/// - the `n` format specifier, [`Specifier::WriteBytesWritten`], is not
///   implemented and will cause an error if encountered.
pub fn fmt_write(w: &mut impl fmt::Write) -> impl FnMut(Argument) -> c_int + '_ {
    use fmt::Write;
    move |Argument {
              flags,
              mut width,
              precision,
              specifier,
          }| {
        let mut w = WriteCounter(w, 0);
        let w = &mut w;
        let res = match specifier {
            Specifier::Percent => w.write_char('%'),
            Specifier::Bytes(data) => write_str(w, flags, width, precision, data),
            Specifier::String(data) => write_str(w, flags, width, precision, data.to_bytes()),
            Specifier::Hex(data) => {
                define_unumeric!(w, data, flags, width, precision.unwrap_or(0), "x")
            }
            Specifier::UpperHex(data) => {
                define_unumeric!(w, data, flags, width, precision.unwrap_or(0), "X")
            }
            Specifier::Octal(data) => {
                define_unumeric!(w, data, flags, width, precision.unwrap_or(0), "o")
            }
            Specifier::Uint(data) => {
                define_unumeric!(w, data, flags, width, precision.unwrap_or(0))
            }
            Specifier::Int(data) => define_numeric!(w, data, flags, width, precision.unwrap_or(0)),
            Specifier::Double { value, format } => match format {
                DoubleFormat::Normal
                | DoubleFormat::UpperNormal
                | DoubleFormat::Auto
                | DoubleFormat::UpperAuto
                | DoubleFormat::Hex
                | DoubleFormat::UpperHex => {
                    define_numeric!(w, value, flags, width, precision.unwrap_or(6))
                }
                DoubleFormat::Scientific => {
                    define_numeric!(w, value, flags, width, precision.unwrap_or(6), "e")
                }
                DoubleFormat::UpperScientific => {
                    define_numeric!(w, value, flags, width, precision.unwrap_or(6), "E")
                }
            },
            Specifier::Char(data) => {
                if flags.contains(Flags::LEFT_ALIGN) {
                    write!(w, "{:width$}", data as char, width = width as usize)
                } else {
                    write!(w, "{:>width$}", data as char, width = width as usize)
                }
            }
            Specifier::Pointer(data) => {
                if flags.contains(Flags::LEFT_ALIGN) {
                    write!(w, "{:<width$p}", data, width = width as usize)
                } else


FF80 0002BBE0  28 06 E0 00 */	cmplwi r6, 0xe000
/* 8002FF84 0002BBE4  41 82 00 14 */	beq lbl_8002FF98
/* 8002FF88 0002BBE8  28 06 FF FF */	cmplwi r6, 0xffff
/* 8002FF8C 0002BBEC  41 82 00 0C */	beq lbl_8002FF98
/* 8002FF90 0002BBF0  39 08 00 01 */	addi r8, r8, 1
/* 8002FF94 0002BBF4  4B FF FF CC */	b lbl_8002FF60
lbl_8002FF98:
/* 8002FF98 0002BBF8  7C 08 22 14 */	add r0, r8, r4
/* 8002FF9C 0002BBFC  2C 00 00 16 */	cmpwi r0, 0x16
/* 8002FFA0 0002BC00  40 80 00 14 */	bge lbl_8002FFB4
/* 8002FFA4 0002BC04  57 C0 08 3C */	slwi r0, r30, 1
/* 8002FFA8 0002BC08  3B DE 00 01 */	addi r30, r30, 1
/* 8002FFAC 0002BC0C  7E B7 03 2E */	sthx r21, r23, r0
/* 8002FFB0 0002BC10  48 00 00 64 */	b lbl_80030014
lbl_8002FFB4:
/* 8002FFB4 0002BC14  28 05 E0 00 */	cmplwi r5, 0xe000
/* 8002FFB8 0002BC18  40 82 00 3C */	bne lbl_8002FFF4
/* 8002FFBC 0002BC1C  57 C0 08 3C */	slwi r0, r30, 1
/* 8002FFC0 0002BC20  38 76 FF FF */	addi r3, r22, -1
/* 8002FFC4 0002BC24  7C 77 03 2E */	sthx r3, r23, r0
/* 8002FFC8 0002BC28  3B DE 00 01 */	addi r30, r30, 1
/* 8002FFCC 0002BC2C  7C 78 CA 14 */	add r3, r24, r25
/* 8002FFD0 0002BC30  7E E4 BB 78 */	mr r4, r23
/* 8002FFD4 0002BC34  7F C5 F3 78 */	mr r5, r30
/* 8002FFD8 0002BC38  3B 7B 00 01 */	addi r27, r27, 1
/* 8002FFDC 0002BC3C  3B 39 01 00 */	addi r25, r25, 0x100
/* 8002FFE0 0002BC40  48 14 70 A1 */	bl func_80177080
/* 8002FFE4 0002BC44  93 DA 00 00 */	stw r30, 0(r26)
/* 8002FFE8 0002BC48  3B C0 00 00 */	li r30, 0
/* 8002FFEC 0002BC4C  38 80 00 00 */	li r4, 0
/* 8002FFF0 0002BC50  48 00 00 24 */	b lbl_80030014
lbl_8002FFF4:
/* 8002FFF4 0002BC54  38 80 00 00 */	li r4, 0
lbl_8002FFF8:
/* 8002FFF8 0002BC58  A0 1F 00 00 */	lhz r0, 0(r31)
/* 8002FFFC 0002BC5C  57 C3 08 3C */	slwi r3, r30, 1
/* 80030000 0002BC60  7C B7 1B 2E */	sthx r5, r23, r3
/* 80030004 0002BC64  3B DE 00 01 */	addi r30, r30, 1
/* 80030008 0002BC68  28 00 E0 00 */	cmplwi r0, 0xe000
/* 8003000C 0002BC6C  41 82


outOrder"]
  SETTABLEKS R3 R20 K2 ["Writable"]
  SETTABLEKS R17 R20 K17 ["Id"]
  LOADB R21 0
  SETTABLEKS R21 R20 K18 ["HideSeparator"]
  SETTABLEKS R10 R20 K9 ["IsGroupGame"]
  CALL R18 2 1
  FASTCALL2 TABLE_INSERT R11 R18 [+5]
  MOVE R20 R11
  MOVE R21 R18
  GETIMPORT R19 K23 [table.insert]
  CALL R19 2 0
  FORGLOOP R13 2 [-28]
  MOVE R13 R6
  LOADNIL R14
  LOADNIL R15
  FORGPREP R13
  GETUPVAL R19 4
  GETTABLEKS R18 R19 K16 ["createElement"]
  GETUPVAL R19 3
  DUPTABLE R20 K28 [{"LayoutOrder", "Writable", "Id", "CurrentPermission", "HideSeparator", "IsGroupGame"}]
  NAMECALL R21 R12 K20 ["getNextOrder"]
  CALL R21 1 1
  SETTABLEKS R21 R20 K1 ["LayoutOrder"]
  SETTABLEKS R3 R20 K2 ["Writable"]
  SETTABLEKS R17 R20 K17 ["Id"]
  GETUPVAL R22 6
  GETTABLEKS R21 R22 K29 ["MultipleKey"]
  SETTABLEKS R21 R20 K27 ["CurrentPermission"]
  LOADB R21 0
  SETTABLEKS R21 R20 K18 ["HideSeparator"]
  SETTABLEKS R10 R20 K9 ["IsGroupGame"]
  CALL R18 2 1
  FASTCALL2 TABLE_INSERT R11 R18 [+5]
  MOVE R20 R11
  MOVE R21 R18
  GETIMPORT R19 K23 [table.insert]
  CALL R19 2 0
  FORGLOOP R13 2 [-33]
  MOVE R13 R5
  LOADNIL R14
  LOADNIL R15
  FORGPREP R13
  GETUPVAL R19 4
  GETTABLEKS R18 R19 K16 ["createElement"]
  GETUPVAL R19 2
  DUPTABLE R20 K26 [{"LayoutOrder", "Writable", "Id", "HideSeparator", "IsGroupGame"}]
  NAMECALL R21 R12 K20 ["getNextOrder"]
  CALL R21 1 1
  SETTABLEKS R21 R20 K1 ["LayoutOrder"]
  SETTABLEKS R3 R20 K2 ["Writable"]
  SETTABLEKS R17 R20 K17 ["Id"]
  LOADB R21 0
  SETTABLEKS R21 R20 K18 ["HideSeparator"]
  SETTABLEKS R10 R20 K9 ["IsGroupGame"]
  CALL R18 2 1
  FASTCALL2 TABLE_INSERT R11 R18 [+5]
  MOVE R20 R11
  MOVE R21 R18
  GETIMPORT R19 K23 [table.insert]
  CALL R19 2 0
  FORGLOOP R13 2 [-28]
  MOVE R13 R7
  LOADNIL R14
  LOADNIL R15
  FORGPREP R13
  GETUPVAL R19 4
  GETTABLEKS R18 R19 K16 ["createElement"]
  GETUPVAL R19 3
  DUPTABLE R20 K28 [{"LayoutOrder", "Writable", "Id", "CurrentPermission", "HideSeparator", "IsGroupGame"}]
  NAMECALL R21 R12 K20 ["getNextOrder"]
  CALL R21 1 1
  SETTABLEKS R21 R20 K1 ["LayoutOrder"]
  SETTABLEKS R3 R20 K2 ["Writable"]
  SETTABLEKS R17 R20 K17 ["Id"]
  GETUPVAL R22 6
  GETTABLEKS R21 R22 K29 ["MultipleKey"]
  SETTABLEKS R21 R20 K27 ["CurrentPermission"]
  LOADB R21 0
  SETTABLEKS R21 R20 K18 ["HideSeparator"]
  SETTABLEKS R10 R20 K9 ["IsGroupGame"]
  CALL R18


        is TACExpr.BinRel.Lt -> this.Lt(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Slt -> this.Slt(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Sle -> this.Sle(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Sgt -> this.Sgt(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Sge -> this.Sge(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Ge -> this.Ge(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Le -> this.Le(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinRel.Eq -> this.Eq(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinOp.BWAnd -> this.BWAnd(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinOp.BWOr -> this.BWOr(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinOp.BWXOr -> this.BWXOr(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)

        is TACExpr.UnaryExp.BWNot -> this.BWNot(rebuildExpr(e.o), e.tag)
        is TACExpr.BinOp.ShiftLeft -> this.ShiftLeft(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinOp.ShiftRightLogical -> this.ShiftRightLogical(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.BinOp.ShiftRightArithmetical -> this.ShiftRightArithmetical(rebuildExpr(e.o1), rebuildExpr(e.o2), e.tag)
        is TACExpr.Apply -> this.Apply(e.f, e.ops.map { rebuildExpr(it) }, e.tag)
        is TACExpr.Select -> this.Select(rebuildExpr(e.base), rebuildExpr(e.loc), e.tag)
        is TACExpr.Store -> this.Store(rebuildExpr(e.base), rebuildExpr(e.loc), rebuildExpr(e.value), e.tag)
        is TACExpr.MultiDimStore -> this.MultiDimStore(
            rebuildExpr(e.base),
            e.locs.map { rebuildExpr(it) },
            rebuildExpr(e.value),
            e.tag
        )
        is TACExpr.MapDefinition -> this.MapDefinition(
            e.defParams.map { rebuildExpr(it) as TACExpr.Sym.Var },
            rebuildExpr(e.definition),
            e.tag
        )
        is TACExpr.LongStore -> this.LongStore(
            rebuildExpr(e.dstMap),
            rebuildExpr(e.dstOffset),
            rebuildExpr(e.srcMap),
            rebuildExpr(e.srcOffset),
            rebuildExpr(e.length),
            e.tag
        )
        is TACExpr.BinBoolOp.LAnd -> this.LAnd(e.ls.map { rebuildExpr(it) }, e.tag)
        is TACExpr.BinBoolOp.LOr -> this.LOr(e.ls.map { rebuildExpr(it) }, e.tag)
        is TACExpr.UnaryExp.LNot -> this.LNot(rebuildExpr(e.o), e.tag)
        is TACExpr.TernaryExp.Ite -> this.Ite(rebuildExpr(e.i), rebuildExpr(e.


ove() = touchBuilder.startFrame(TouchEvent.Type.MOVE)
    fun dispatchTouchEventStartEnd() = touchBuilder.startFrame(TouchEvent.Type.END)
    fun dispatchTouchEventAddTouch(id: Int, x: Float, y: Float) = touchBuilder.touch(id, Point(x, y))
    fun dispatchTouchEventEnd() = gameWindow.dispatch(touchBuilder.endFrame().reset())

    private fun addTouches(touches: Set<*>, type: TouchType) {
        //println("addTouches[${touches.size}] type=$type");
        for (touch in touches) {
            if (touch !is UITouch) {
                logger.info { "ERROR.addTouches no UITouch" }
                continue
            }
            val point = touch.locationInView(this.view)
            var index = this.touches.indexOf(touch)

            if (index < 0) {
                index = this.touches.size
                this.touches.add(touch)
                this.touchesIds.add(freeIds.alloc())
            }

            val uid = touchesIds[index]

            //printf(" - %d: %d, %d\n", (int)num.intValue, (int)point.x, (int)point.y);

            val pointX = point.useContents { x.toFloat() }
            val pointY = point.useContents { y.toFloat() }
            val px = pointX * this.view.contentScaleFactor.toFloat()
            val py = pointY * this.view.contentScaleFactor.toFloat()
            this.dispatchTouchEventAddTouch(uid, px, py)

            //println(" - TOUCH. index=$index, uid=$uid, px=$px, py=$py")

            if (type == TouchType.ENDED) {
                freeIds.free(uid)
                this.touches.removeAt(index)
                this.touchesIds.removeAt(index)
            }
        }
    }
}

open class IosGameWindow(
    val windowProvider: (() -> UIWindow?)? = null,
    val glXViewControllerProvider: (() -> MyGLKViewController?)? = null,
) : GameWindow() {
    override val ag: AG = AGOpengl(KmlGlNative().checkedIf(checked = false))
    //override val ag: AG = AGOpengl(KmlGlNative().checkedIf(checked = true, printStackTrace = true))

    override val pixelsPerInch: Double get() = UIScreen.mainScreen.scale * 160.0

    val window: UIWindow get() = windowProvider?.invoke()
        ?: UIApplication.sharedApplication.keyWindow
        ?: (UIApplication.sharedApplication.windows.first() as UIWindow)

    override val dialogInterface = DialogInterfaceIos(this)

    val glXViewController: MyGLKViewController? get() = glXViewControllerProvider?.invoke()

    override fun close(exitCode: Int) {
        println("Not closing with exitCode=$exitCode")
        //UIApplication.sharedApplication.terminate
        super.close(exitCode)
    }

    override var preferredFps: Int = GameWindow.DEFAULT_PREFERRED_FPS
        get() = glXViewController?.preferredFramesPerSecond?.toInt() ?: field
        set(value) {
            field = value
            glXViewController?.preferredFramesPerSecond = value.convert()
        }
    override var fps: Int get() = 60; set(value) = Unit
    //override var title: String get() = ""; set(value) = Unit
    //override val width: Int get() = 512
    //override val height: Int get() = 512
    //override var icon: Bitmap? get() = null; set(value) = Unit
    //override var fullscreen: Boolean get() = false; set(value) = Unit
    //override var visible: Boolean get() = false; set(value) = Unit
    //override var quality: Quality get() = Quality.AUTOMATIC; set(value) = Unit

    override suspend fun loop(entry: suspend GameWindow.() -> Unit) {
        println("YAY! IosGameWindow.loop")
        // Trick to reference some classes to make them


 form:
	Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
where the fields are defined as follows:
	L                A single character, representing the log level (eg 'I' for INFO)
	mm               The month (zero padded; ie May is '05')
	dd               The day (zero padded)
	hh:mm:ss.uuuuuu  Time in hours, minutes and fractional seconds
	threadid         The space-padded thread ID as returned by GetTID()
	file             The file name
	line             The line number
	msg              The user-supplied message
*/
func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
	if l.verbosity <= 0 {
		buf := l.getBuffer()
		now := timeNow()
		_, month, day := now.Date()
		hour, minute, second := now.Clock()
		// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
		buf.tmp[0] = severityChar[s]
		buf.tmp[1] = ' '
		buf.twoDigits(2, int(month))
		buf.twoDigits(4, day)
		buf.tmp[6] = ' '
		buf.twoDigits(7, hour)
		buf.tmp[9] = ':'
		buf.twoDigits(10, minute)
		buf.tmp[12] = ':'
		buf.twoDigits(13, second)
		buf.tmp[15] = ']'
		buf.tmp[16] = ' '
		buf.Write(buf.tmp[:17])
		return buf, "", 0
	}
	_, file, line, ok := runtime.Caller(3 + depth)
	if !ok {
		file = "???"
		line = 1
	} else {
		slash := strings.LastIndex(file, "/")
		if slash >= 0 {
			file = file[slash+1:]
		}
	}
	return l.formatHeader(s, file, line), file, line
}

// formatHeader formats a log header using the provided file name and line number.
func (l *loggingT) formatHeader(s severity, file string, line int) *buffer {
	now := timeNow()
	if line < 0 {
		line = 0 // not a real line number, but acceptable to someDigits
	}
	if s > fatalLog {
		s = infoLog // for safety.
	}
	buf := l.getBuffer()

	// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
	// It's worth about 3X. Fprintf is hard.
	_, month, day := now.Date()
	hour, minute, second := now.Clock()
	// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
	buf.tmp[0] = severityChar[s]
	buf.twoDigits(1, int(month))
	buf.twoDigits(3, day)
	buf.tmp[5] = ' '
	buf.twoDigits(6, hour)
	buf.tmp[8] = ':'
	buf.twoDigits(9, minute)
	buf.tmp[11] = ':'
	buf.twoDigits(12, second)
	buf.tmp[14] = '.'
	buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
	buf.tmp[21] = ' '
	buf.nDigits(7, 22, pid, ' ') // TODO: should be TID
	buf.tmp[29] = ' '
	buf.Write(buf.tmp[:30])
	buf.WriteString(file)
	buf.tmp[0] = ':'
	n := buf.someDigits(1, line)
	buf.tmp[n+1] = ']'
	buf.tmp[n+2] = ' '
	buf.Write(buf.tmp[:n+3])
	return buf
}

// Some custom tiny helper functions to print the log header efficiently.

const digits = "012


ame);

                root.AddChild(item);
                treeViewItems.Add(item);
            }
        }

        private void AddSearchItem(List<TreeViewItem> treeViewItems, TreeViewItem root)
        {
            List<(TreeViewItem, int)> collects = new List<(TreeViewItem, int)>();

            int count = this.graphView.nodeViews.Count;
            for (int i = 0; i < count; i++)
            {
                IEditorNodeView nodeView = this.graphView.nodeViews[i];

                int id = nodeView.asset.id.GetHashCode();
                nodeViews.Add(id, nodeView);

                string displayName = ObjectDescriptionUtility.GetDescription(nodeView.asset);
                if (string.IsNullOrEmpty(displayName)) displayName = nodeView.asset.name;

                int score = SearchUtility.Search(displayName, searchString);
                if (score == 0) continue;

                TreeViewItem item = new TreeViewItem(id, 0, displayName);
                collects.Add((item,score));
            }

            collects.Sort((a, b) => b.Item2.CompareTo(a.Item2));

            foreach (var collect in collects)
            {
                root.AddChild(collect.Item1);
                treeViewItems.Add(collect.Item1);
            }
        }

        protected override void SingleClickedItem(int id)
        {
            base.SingleClickedItem(id);
            IEditorNodeView nodeView = nodeViews.GetValueOrDefault(id);
            if (nodeView == null) return;

            this.graphView.SetSelection(new List<ISelectable> {nodeView.element});
            this.graphView.FrameSelection();
        }
    }
}


['referenceStoreId'] as String,
      roleArn: json['roleArn'] as String,
      status: ReferenceImportJobStatus.fromString((json['status'] as String)),
      completionTime: timeStampFromJson(json['completionTime']),
    );
  }

  Map<String, dynamic> toJson() {
    final creationTime = this.creationTime;
    final id = this.id;
    final referenceStoreId = this.referenceStoreId;
    final roleArn = this.roleArn;
    final status = this.status;
    final completionTime = this.completionTime;
    return {
      'creationTime': iso8601ToJson(creationTime),
      'id': id,
      'referenceStoreId': referenceStoreId,
      'roleArn': roleArn,
      'status': status.value,
      if (completionTime != null)
        'completionTime': iso8601ToJson(completionTime),
    };
  }
}

/// An genome reference source.
class ImportReferenceSourceItem {
  /// The source's status.
  final ReferenceImportJobItemStatus status;

  /// The source's description.
  final String? description;

  /// The source's name.
  final String? name;

  /// The source's reference ID.
  final String? referenceId;

  /// The source file's location in Amazon S3.
  final String? sourceFile;

  /// The source's status message.
  final String? statusMessage;

  /// The source's tags.
  final Map<String, String>? tags;

  ImportReferenceSourceItem({
    required this.status,
    this.description,
    this.name,
    this.referenceId,
    this.sourceFile,
    this.statusMessage,
    this.tags,
  });

  factory ImportReferenceSourceItem.fromJson(Map<String, dynamic> json) {
    return ImportReferenceSourceItem(
      status:
          ReferenceImportJobItemStatus.fromString((json['status'] as String)),
      description: json['description'] as String?,
      name: json['name'] as String?,
      referenceId: json['referenceId'] as String?,
      sourceFile: json['sourceFile'] as String?,
      statusMessage: json['statusMessage'] as String?,
      tags: (json['tags'] as Map<String, dynamic>?)
          ?.map((k, e) => MapEntry(k, e as String)),
    );
  }

  Map<String, dynamic> toJson() {
    final status = this.status;
    final description = this.description;
    final name = this.name;
    final referenceId = this.referenceId;
    final sourceFile = this.sourceFile;
    final statusMessage = this.statusMessage;
    final tags = this.tags;
    return {
      'status': status.value,
      if (description != null) 'description': description,
      if (name != null) 'name': name,
      if (referenceId != null) 'referenceId': referenceId,
      if (sourceFile != null) 'sourceFile': sourceFile,
      if (statusMessage != null) 'statusMessage': statusMessage,
      if (tags != null) 'tags': tags,
    };
  }
}

enum JobStatus {
  submitted('SUBMITTED'),
  inProgress('IN_PROGRESS'),
  cancelled('CANCELLED'),
  completed('COMPLETED'),
  failed('FAILED'),
  completedWithFailures('COMPLETED_WITH_FAILURES'),
  ;

  final String value;

  const JobStatus(this.value);

  static JobStatus fromString(String value) => values.firstWhere(
      (e) => e.value == value,
      orElse: () => throw Exception('$value is not known in enum JobStatus'));
}

/// A filter for annotation import jobs.
class ListAnnotationImportJobsFilter {
  /// A status to filter on.
  final JobStatus? status;

  /// A store name to filter on.
  final String? storeName;

  ListAnnotationImportJobsFilter({
    this.status,
    this.storeName,
  });

  Map<String, dynamic> toJson() {
    final status = this.status;
    final storeName = this.storeName;
    return


Location.ios(userLocation));
    }
  }

  @override
  Future<void> mapView_didAnnotationViewCalloutTapped(
    MAMapView mapView,
    MAAnnotationView view,
  ) async {
    await super.mapView_didAnnotationViewCalloutTapped(mapView, view);
    if (onInfoWindowClicked != null) {
      await onInfoWindowClicked(
        Marker.ios(
          MAPointAnnotation()
            ..refId = (await view.get_annotation(viewChannel: false)).refId,
          iosController,
        ),
      );
    }
  }

  @override
  Future<void> mapView_didAddOverlayRenderers(
    MAMapView mapView,
    List<dynamic> overlayRenderers,
  ) async {
    await super.mapView_didAddOverlayRenderers(mapView, overlayRenderers);
    if (overlayRenderers.length == 1 &&
        await TypeOpAmapMapFluttifyIOS(overlayRenderers[0])
            .is__<MAMultiPointOverlayRenderer>()) {
      final multiPointRenderer = TypeOpAmapMapFluttifyIOS(overlayRenderers[0])
          .as__<MAMultiPointOverlayRenderer>();
      await multiPointRenderer.set_delegate(this);
    }
  }

  @override
  Future<void> multiPointOverlayRenderer_didItemTapped(
    MAMultiPointOverlayRenderer renderer,
    MAMultiPointItem item,
  ) async {
    await super.multiPointOverlayRenderer_didItemTapped(renderer, item);
    if (onMultiPointClicked != null) {
      final id = await item.get_customID();
      final title = await item.get_title();
      final snippet = await item.get_subtitle();
      final object = await item.getJsonableProperty__(1);
      await onMultiPointClicked(id, title, snippet, object);
    }
  }
}

class _AndroidMapDelegate extends java_lang_Object
    with
        com_amap_api_maps_AMap_OnMarkerClickListener,
        com_amap_api_maps_AMap_OnMarkerDragListener,
        com_amap_api_maps_AMap_OnMapClickListener,
        com_amap_api_maps_AMap_OnMapLongClickListener,
        com_amap_api_maps_AMap_OnCameraChangeListener,
        com_amap_api_maps_AMap_OnMapScreenShotListener,
        com_amap_api_maps_AMap_OnMyLocationChangeListener,
        com_amap_api_maps_AMap_OnInfoWindowClickListener,
        com_amap_api_maps_AMap_OnMapLoadedListener,
        com_amap_api_maps_AMap_OnMultiPointClickListener {
  OnMarkerClicked onMarkerClicked;
  OnMarkerDrag onMarkerDragStarted;
  OnMarkerDrag onMarkerDragging;
  OnMarkerDrag onMarkerDragEnded;
  OnMapMove onMapMoveStart;
  OnMapMove onMapMoving;
  OnMapMove onMapMoveEnd;
  OnMapClicked onMapClicked;
  OnMapClicked onMapLongClicked;
  ValueChanged<Uint8List> onSnapshot;
  OnLocationChange onLocationChange;
  OnMarkerClicked onInfoWindowClicked;
  OnMultiPointClicked onMultiPointClicked;

  bool _moveStarted = false;

  @override
  Future<bool> onMarkerClick(com_amap_api_maps_model_Marker var1) async {
    await super.onMarkerClick(var1);
    if (onMarkerClicked != null) {
      await onMarkerClicked(Marker.android(var1));
    }


-content .layui-icon-success{color:#16b777}.layui-layer-dialog .layui-layer-content .layui-icon-error{top:19px;color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-question{color:#ffb800}.layui-layer-dialog .layui-layer-content .layui-icon-lock{color:#787878}.layui-layer-dialog .layui-layer-content .layui-icon-face-cry{color:#ff5722}.layui-layer-dialog .layui-layer-content .layui-icon-face-smile{color:#16b777}.layui-layer-rim{border:6px solid #8d8d8d;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #d3d4d3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-close{color:#fff}.layui-layer-hui .layui-layer-content{padding:11px 24px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:18px 24px 18px 58px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:76px;height:38px;line-height:38px;text-align:center}.layui-layer-loading-icon{font-size:38px;color:#959595}.layui-layer-loading2{text-align:center}.layui-layer-loading-2{position:relative;height:38px}.layui-layer-loading-2:after,.layui-layer-loading-2:before{content:'';position:absolute;left:50%;top:50%;width:38px;height:38px;margin:-19px 0 0 -19px;border-radius:50%;border:3px solid #d2d2d2;box-sizing:border-box}.layui-layer-loading-2:after{border-color:transparent;border-left-color:#1e9fff}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:8px 15px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layu


::ffi::c_void;
pub type CompassDataThreshold = *mut ::core::ffi::c_void;
pub type CompassReading = *mut ::core::ffi::c_void;
pub type CompassReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type Gyrometer = *mut ::core::ffi::c_void;
pub type GyrometerDataThreshold = *mut ::core::ffi::c_void;
pub type GyrometerReading = *mut ::core::ffi::c_void;
pub type GyrometerReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type HingeAngleReading = *mut ::core::ffi::c_void;
pub type HingeAngleSensor = *mut ::core::ffi::c_void;
pub type HingeAngleSensorReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type ISensorDataThreshold = *mut ::core::ffi::c_void;
pub type Inclinometer = *mut ::core::ffi::c_void;
pub type InclinometerDataThreshold = *mut ::core::ffi::c_void;
pub type InclinometerReading = *mut ::core::ffi::c_void;
pub type InclinometerReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type LightSensor = *mut ::core::ffi::c_void;
pub type LightSensorDataThreshold = *mut ::core::ffi::c_void;
pub type LightSensorReading = *mut ::core::ffi::c_void;
pub type LightSensorReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type Magnetometer = *mut ::core::ffi::c_void;
#[doc = "*Required features: 'Devices_Sensors'*"]
#[repr(transparent)]
pub struct MagnetometerAccuracy(pub i32);
impl MagnetometerAccuracy {
    pub const Unknown: Self = Self(0i32);
    pub const Unreliable: Self = Self(1i32);
    pub const Approximate: Self = Self(2i32);
    pub const High: Self = Self(3i32);
}
impl ::core::marker::Copy for MagnetometerAccuracy {}
impl ::core::clone::Clone for MagnetometerAccuracy {
    fn clone(&self) -> Self {
        *self
    }
}
pub type MagnetometerDataThreshold = *mut ::core::ffi::c_void;
pub type MagnetometerReading = *mut ::core::ffi::c_void;
pub type MagnetometerReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type OrientationSensor = *mut ::core::ffi::c_void;
pub type OrientationSensorReading = *mut ::core::ffi::c_void;
pub type OrientationSensorReadingChangedEventArgs = *mut ::core::ffi::c_void;
pub type Pedometer = *mut ::core::ffi::c_void;
pub type PedometerDataThreshold = *mut ::core::ffi::c_void;
pub type PedometerReading = *mut ::core::ffi::c_void;
pub type PedometerReadingChangedEventArgs = *mut ::core::ffi::c_void;
#[doc = "*Required features: 'Devices_Sensors'*"]
#[repr(transparent)]
pub struct PedometerStepKind(pub i32);
impl PedometerStepKind {
    pub const Unknown: Self = Self(0i32);
    pub const Walking: Self = Self(1i32);
    pub const Running: Self = Self(2i32);
}
impl ::core::marker::Copy for PedometerStepKind {}
impl ::core::clone::Clone for PedometerStepKind {
    fn clone(&self) -> Self {
        *self
    }
}
pub type ProximitySensor = *mut ::core::ffi::c_void;
pub type ProximitySensorDataThreshold = *mut ::core::ffi::c_void;
pub type ProximitySensorDisplayOnOffController = *mut ::core::ffi::c_void;
pub type ProximitySensorReading = *mut ::core::ffi::c_void;
pub type Proximity


tchesPathLength(requestPath, ltab.Contents)
					if ltpl > maxl {
						selected = i
					}
					ret = append(ret, lt)
					i += 1
				}
			}
		}
	}
	if selected > -1 {
		ret[selected].Selected = true
	}
	return ret
}

func GetFirstTabPath(tabContent []LowerTabContent) string {
	for _, tc := range tabContent {
		if tc.Path != "" {
			return tc.Path
		}
		if len(tc.Section) > 0 {
			return GetFirstTabPath(tc.Section)
		}
	}
	return ""
}

func LowerTabMatchesPathLength(requestPath string, tabContent []LowerTabContent) int {
	ret := -1
	for _, tc := range tabContent {
		if tc.Path == requestPath {
			return len(tc.Path)
		} else if strings.HasPrefix(requestPath, tc.Path) {
			ret = max(ret, len(tc.Path))
		}
		if len(tc.Section) > 0 {
			ltpl := LowerTabMatchesPathLength(requestPath, tc.Section)
			ret = max(ret, ltpl)
			if ret == len(requestPath) {
				break
			}
		}
	}
	return ret
}

func LowerTabMatchesPath(requestPath string, tabContent []LowerTabContent) bool {
	return LowerTabMatchesPathLength(requestPath, tabContent) == len(requestPath)
}

func GetLeftNav(requestPath string, book Book) string {
	var currentUpperTab UpperTab
	for _, upperTab := range book.UpperTabs {
		if upperTab.Path != "" && strings.HasPrefix(requestPath, upperTab.Path) {
			currentUpperTab = upperTab
			break
		}
	}
	if currentUpperTab.Path == "" {
		return ""
	}
	for _, lt := range currentUpperTab.LowerTabs.Other {
		if len(lt.Contents) == 1 && len(lt.Contents[0].Section) == 0 {
			continue
		}
		if LowerTabMatchesPath(requestPath, lt.Contents) {
			result := "
\n"
			result += BuildLeftNav(requestPath, lt.Contents)
			result += "
\n"
			return result
		}

	}
	return ""
}

func BuildLeftNav(requestPath string, ltc []LowerTabContent) string {
	result := ""
	for _, item := range ltc {
		if item.Path != "" {
			itemClass := "devsite-nav-item"
			if item.Status != "" {
				itemClass += " devsite-nav-has-status devsite-nav-" + item.Status
			}
			if strings.HasPrefix(requestPath, item.Path) && strings.Count(requestPath, "/") == strings.Count(item.Path, "/") {
				itemClass += " devsite-nav-active"
			}
			result += "
\n"
			result += "\n"
			result += ""
			result += "" + html.EscapeString(item.Title) + "\n"
			result += ""
			if item.Status != "" {
				result += ""
				result += ""
				result += ""
			}
			result += "\n"
			result += "
\n"
		} else if item.Heading != "" {
			result += "
\n"
			result += "<


:100;
	height:30;
	text-align:center;
	background-color:#A0A0A0;
}
.Button A
{
	color:White;
	text-decoration:none;
	font-size:16pt;
	font-family:Courier;
	font-weight:600;
}
.BigPushedButton
{
	width:116;
	height:24;
	text-align:center;
	background-color:White;
	color:Gray;
	font-size:15pt;
	font-family:Courier;
	font-weight:600;
}
.BigUnderButton
{
	width:120;
	height:30;
	text-align:center;
	background-color:Gray;
}
.Big2PushedButton
{
	width:136;
	height:24;
	text-align:center;
	background-color:White;
	color:Gray;
	font-size:15pt;
	font-family:Courier;
	font-weight:600;
}
.Big2UnderButton
{
	width:140;
	height:30;
	text-align:center;
	background-color:Gray;
}
.PushedButton
{
	width:96;
	height:24;
	text-align:center;
	background-color:White;
	color:Gray;
	font-size:15pt;
	font-family:Courier;
	font-weight:600;
}
.UnderButton
{
	width:100;
	height:30;
	text-align:center;
	background-color:Gray;
}

.SmallLettersButton
{
	width:100;
	height:30;
	text-align:center;
	background-color:#A0A0A0;
}
.SmallLettersButton A
{
	color:White;
	text-decoration:none;
	font-size:14pt;
	font-family:Courier;
	font-weight:600;
}
.BigButton
{
	width:120;
	height:30;
	text-align:center;
	background-color:#A0A0A0;
}
.BigButton A
{
	color:White;
	text-decoration:none;
	font-size:16pt;
	font-family:Courier;
	font-weight:600;
}
.Big2Button
{
	width:140;
	height:30;
	text-align:center;
	background-color:#A0A0A0;
}
.Big2Button A
{
	color:White;
	text-decoration:none;
	font-size:16pt;
	font-family:Courier;
	font-weight:600;
}
.ShortButton
{
	width:60;
	height:30;
	text-align:center;
	background-color:#A0A0A0;
}
.ShortButton A
{
	color:White;
	text-decoration:none;
	font-size:16pt;
	font-family:Courier;
	font-weight:600;
}
.ShortPushedButton
{
	width:56;
	height:24;
	text-align:center;
	background-color:White;
	color:Gray;
	font-size:15pt;
	font-family:Courier;
	font-weight:600;
}
.ShortUnderButton
{
	width:60;
	height:30;
	text-align:center;
	background-color:Gray;
}
@use '../../variables' as *;
@use '../../mixins' as *;
@use 'sass:color';

.song-player-page {
  width: 100%;
  max-width: 100%;
  padding: 0;

  .song-player-container {
    margin-top: 25px;
    max-width: 100% !important;
    padding: 0 16px !important;

    .song-player-content {
      margin-top: 25px;
      background-color: transparent;
      border-radius: 8


# -*- coding: utf-8 -*-
#
# RERO ILS
# Copyright (C) 2019-2022 RERO
# Copyright (C) 2019-2022 UCLouvain
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Signals connector for Budgets."""

from rero_ils.modules.acquisition.acq_accounts.api import (
    AcqAccountsIndexer,
    AcqAccountsSearch,
)
from rero_ils.modules.acquisition.budgets.api import Budget
from rero_ils.modules.tasks import process_bulk_queue

def budget_is_active_changed(sender, record=None, *args, **kwargs):
    """Reindex related account if is_active field changes."""
    if isinstance(record, Budget):
        ori_record = Budget.get_record_by_pid(record.pid)
        if ori_record["is_active"] != record["is_active"]:
            search = AcqAccountsSearch().filter("term", budget__pid=record.pid).source().scan()
            uuids = [hit.meta.id for hit in search]
            AcqAccountsIndexer().bulk_index(uuids)
            process_bulk_queue.apply_async()


##### ethereum/execution-spec-tests
- [Repo link](https://github.com/ethereum/execution-spec-tests)
- 特点
  - Python源码
  - pytest 提供支持，并提供简单到复杂的参数化
  - 由于转换功能，仍然需要实际的客户端实现来填充
- 规范测试
  ![alt text](img/step/ExecutionSpecTesting.png)
  - 从包含所有书面参数化的 Python 测试开始
    - 目前，从 Frontier 到 Cancun，每个分支都有一个 Python 测试
  - 三个依赖关系
    - Evm t8n：Geth sub-command evm t8n
      - 理由：由于测试用例是用Python编写的，开发人员需要执行客户端来提供实际的客户端实现
      - 命令输入：所有预状态、交易和环境
      - 输出：执行结果
    - Solidity: (开发人员在测试中越来越少使用)
      - 仅当开发人员无法通过字节码编写来完成非常复杂的代码时才使用 Solidity
    - EIP/ EIPs：开发人员编写测试时规范的主要来源
  - Two main sub repos: Source & Tests
    - Src: https://github.com/ethereum/execution-spec-tests/tree/main/src
      - 框架的源代码，即开发人员用来填充测试的代码
      - src里没有测试
    - Tests: https://github.com/ethereum/execution-spec-tests/tree/main/tests
      - Incl. hardfork tests, from frontier to cancun
      - 由于 ethereum/execution-spec-tests 存储库是从上海升级激活的，上海和cancun对所有 EIP 进行了测试，而对于之前的 EIP，完整测试将在 ethereum/tests repo中
### 4.20
#### FuzzyVM
- [repo link](https://github.com/MariusVanDerWijden/FuzzyVM)
- fuzz EVM框架
  - FuzzyVM 创建状态测试，可用于相互区分fuzz EVM 实现
  - 它只关注测试生成部分，测试执行部分由[Go evmlab](https://github.com/holiman/goevmlab)处理
#### 执行 API 测试
- [repo link](https://github.com/ethereum/execution-apis/tree/main/tests)
- 测试用于查询执行客户端的所有执行 API
#### 共识层测试
- [repo link](https://github.com/ethereum/consensus-specs/tree/dev/tests)
#### 特点
- 在规范中独立，因此可以在同一个repo中编写和填写测试，而不依赖于任何共识层客户端
- 在生成所有客户端都可以使用的不同格式的测试fixture方面也有类似的想法
- python 实现
#### 共识层测试格式
- [repo link](https://github.com/ethereum/consensus-specs/tree/dev/tests/form


�令** 用来将DOS格式的文本文件转换成UNIX格式的（DOS/MAC to UNIX text file format converter）。DOS下的文本文件是以`\r\n`作为断行标志的，表示成十六进制就是0D 0A。而Unix下的文本文件是以\n作为断行标志的，表示成十六进制就是0A。DOS格式的文本文件在Linux底下，用较低版本的vi打开时行尾会显示`^M`，而且很多命令都无法很好的处理这种格式的文件，如果是个shell脚本，。而Unix格式的文本文件在Windows下用Notepad打开时会拼在一起显示。因此产生了两种格式文件相互转换的需求，对应的将UNIX格式文本文件转成成DOS格式的是unix2dos命令。

### 语法

```
dos2unix [-hkqV] [-c convmode] [-o file ...] [-n infile outfile ...]
```

### 选项

```
-k：保持输出文件的日期不变
-q：安静模式，不提示任何警告信息。
-V：查看版本
-c：转换模式，模式有：ASCII, 7bit, ISO, Mac, 默认是：ASCII。
-o：写入到源文件
-n：写入到新文件
```

### 参数

参数：需要转换到文件。

### 实例

最简单的用法就是dos2unix直接跟上文件名：

```
dos2unix file
```

如果一次转换多个文件，把这些文件名直接跟在dos2unix之后。（注：也可以加上`-o`参数，也可以不加，效果一样）

```
dos2unix file1 file2 file3
dos2unix -o file1 file2 file3
```

上面在转换时，都会直接在原来的文件上修改，如果想把转换的结果保存在别的文件，而源文件不变，则可以使用`-n`参数。

```
dos2unix oldfile newfile
```

如果要保持文件时间戳不变，加上`-k`参数。所以上面几条命令都是可以加上`-k`参数来保持文件时间戳的。

```
dos2unix -k file
dos2unix -k file1 file2 file3
dos2unix -k -o file1 file2 file3
dos2unix -k -n oldfile newfile
```

<!-- Linux命令行搜索引擎：https://jaywcjlove.github.io/linux-command/ -->pstree
===

以树状图的方式展现进程之间的派生关系

## 补充说明

**pstree命令** 以树状图的方式展现进程之间的派生关系，显示效果比较直观。

### 语法

```
pstree(选项)
```

### 选项

```
-


ity:1}.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition:width .5s ease,opacity .5s ease}.tox .tox-selector{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;display:inline-block;height:10px;position:absolute;width:10px}.tox.tox-platform-touch .tox-selector{height:12px;width:12px}.tox .tox-slider{align-items:center;display:flex;flex:1;height:24px;justify-content:center;position:relative}.tox .tox-slider__rail{background-color:transparent;border:1px solid #000;border-radius:3px;height:10px;min-width:120px;width:100%}.tox .tox-slider__handle{background-color:#207ab7;border:2px solid #185d8c;border-radius:3px;box-shadow:none;height:24px;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:14px}.tox .tox-form__controls-h-stack>.tox-slider:not(:first-of-type){margin-inline-start:8px}.tox .tox-form__controls-h-stack>.tox-form__group+.tox-slider{margin-inline-start:32px}.tox .tox-form__controls-h-stack>.tox-slider+.tox-form__group{margin-inline-start:32px}.tox .tox-source-code{overflow:auto}.tox .tox-spinner{display:flex}.tox .tox-spinner>div{animation:tam-bouncing-dots 1.5s ease-in-out 0s infinite both;background-color:rgba(255,255,255,.5);border-radius:100%;height:8px;width:8px}.tox .tox-spinner>div:nth-child(1){animation-delay:-.32s}.tox .tox-spinner>div:nth-child(2){animation-delay:-.16s}@keyframes tam-bouncing-dots{0%,100%,80%{transform:scale(0)}40%{transform:scale(1)}}.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left:4px}.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right:4px}.tox .tox-statusbar{align-items:center;background-color:#222f3e;border-top:1px solid #000;color:#fff;display:flex;flex:0 0 auto;font-size:12px;font-weight:400;height:18px;overflow:hidden;padding:0 8px;position:relative;text-transform:uppercase}.tox .tox-statusbar__path{display:flex;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tox .tox-statusbar__right-container{display:flex;justify-content:flex-end;white-space:nowrap}.tox .tox-statusbar__help-text{text-align:center}.tox .tox-statusbar__text-container{display:flex;flex:1 1 auto;justify-content:space-between;overflow:hidden}@media only screen and (min-width:768px){.tox .tox-statusbar__text-container.tox-statusbar__text-container-3-cols>.tox-statusbar__help-text,.tox .tox-statusbar__text-container.tox-statusbar__text-container-3-cols>.tox-statusbar__path,.tox .tox-statusbar__text-container.tox-statusbar__text-container-3-cols>.tox-statusbar__right-container{flex:0 0 calc(100% / 3)}}.tox .tox-statusbar__text-container.tox-statusbar__text-container--flex-end{justify-content:flex-end}.tox .tox-statusbar__text-container.tox-statusbar__text-container--flex-start{justify-content:flex-start}.tox .tox-statusbar__


 fun createOrUpdateTask(
        projectId: String,
        repoName: String,
        request: RemoteConfigCreateRequest,
        clusterInfo: ClusterNodeInfo
    ): ReplicaTaskInfo {
        with(request) {
            // TODO 临时处理，在创建一次性任务时进行鉴权，后续需要修改为在执行一次性任务时进行鉴权
            clusterNodePermissionService.checkRepoPermission(
                clusterInfo, remoteUserUsername, remoteUserPassword, remoteProjectId, remoteRepoName
            )

            val repositoryDetail = localDataManager.findRepoByName(projectId, repoName)
            // 只有在同构集群内部才可以通过一次性分发任务进行仓库同步
            validateReplicaObject(request, clusterInfo)
            val replicaObjectType = getReplicaObjectType(request)
            val replicaTaskObjects = buildReplicaTaskObjects(
                repoName, repositoryDetail.type, replicaObjectType, request
            )
            var task = replicaTaskService.getByTaskName(NAME.format(projectId, repoName, name))
            if (task == null) {
                val taskCreateRequest = ReplicaTaskCreateRequest(
                    name = NAME.format(projectId, repoName, name),
                    localProjectId = projectId,
                    replicaObjectType = replicaObjectType,
                    replicaTaskObjects = replicaTaskObjects,
                    replicaType = replicaType,
                    setting = setting,
                    remoteClusterIds = setOf(clusterInfo.id!!),
                    description = description,
                    enabled = enable
                )
                task = replicaTaskService.create(taskCreateRequest)
            } else {
                val taskUpdateRequest = ReplicaTaskUpdateRequest(
                    key = task.key,
                    name = task.name,
                    localProjectId = projectId,
                    replicaTaskObjects = replicaTaskObjects,
                    replicaObjectType = replicaObjectType,
                    setting = setting,
                    remoteClusterIds = setOf(clusterInfo.id!!),
                    description = description,
                )
                replicaTaskService.update(taskUpdateRequest)?.let {
                    task = it.copy()
                }
            }
            logger.info(
                toJson(
                    convertToReplicationTaskMetricsRecord(
                        projectId = projectId,
                        repoName = repoName,
                        repoType = repositoryDetail.type.name,
                        request = request,
                        replicaTaskInfo = task!!
                    )
                )
            )
            return task!!
        }
    }

    /**
     * 校验分发内容
     */
    private fun validateReplicaObject(
        request: RemoteConfigCreateRequest,
        clusterInfo: ClusterNodeInfo
    ) {
        with(request) {
            // 兼容历史数据，replicaObjectType为空的情况
            if (pathConstraints.isNullOrEmpty() && packageConstraints.isNullOrEmpty() &&
                clusterInfo.type == ClusterNodeType.REMOTE) {
                throw ErrorCodeException(CommonMessageCode.PARAMETER_INVALID, "Package or path")
            }

            if (pathConstraints.isNullOrEmpty() && packageConstraints.isNullOrEmpty() &&
                replicaObjectType != ReplicaObjectType.REPOSITORY) {
                throw ErrorCodeException(CommonMessageCode.PARAMETER_INVALID, "Package or path")
            }
        }
    }

    /**
     * 获取对应分发任务的内容类型
     */
    private fun getReplicaObjectType(request: RemoteConfigCreateRequest): ReplicaObjectType {
        with(request) {
            if (replicaObjectType != null) return replicaObjectType!!
            return if (replicaType == ReplicaType.RUN_ONCE) {
                if (!pathConstraints.isNullOrEmpty()) {
                    ReplicaObjectType.PATH
                } else {
                    ReplicaObjectType.PACKAGE


ng
TEST_CASE("concurrent_multimap::swap with not always equal allocator") {
    using not_always_equal_alloc_mmap_type = tbb::concurrent_multimap<int, int, std::less<int>,
                                                                      NotAlwaysEqualAllocator<std::pair<const int, int>>>;
    test_swap_not_always_equal_allocator<not_always_equal_alloc_mmap_type>();
}

#if TBB_USE_EXCEPTIONS
//! \brief \ref error_guessing
TEST_CASE("concurrent_map throwing copy constructor") {
    using exception_map_type = tbb::concurrent_map<ThrowOnCopy, ThrowOnCopy>;
    test_exception_on_copy_ctor<exception_map_type>();
}

//! \brief \ref error_guessing
TEST_CASE("concurrent_multimap throwing copy constructor") {
    using exception_mmap_type = tbb::concurrent_multimap<ThrowOnCopy, ThrowOnCopy>;
    test_exception_on_copy_ctor<exception_mmap_type>();
}
#endif // TBB_USE_EXCEPTIONS

#if __TBB_CPP20_CONCEPTS_PRESENT
//! \brief \ref error_guessing
TEST_CASE("container_range concept for concurrent_map ranges") {
    static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::range_type>);
    static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::const_range_type>);
}

//! \brief \ref error_guessing
TEST_CASE("container_range concept for concurrent_multimap ranges") {
    static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::range_type>);
    static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::const_range_type>);
}
#endif // __TBB_CPP20_CONCEPTS_PRESENT
/*
    Copyright (c) 2005-2023 Intel Corporation

    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.
*/

#if __INTEL_COMPILER && _MSC_VER
#pragma warning(disable : 2586) // decorated name length exceeded, name was truncated
#endif

#define TBB_DEFINE_STD_HASH_SPECIALIZATIONS 1
#include <tbb/concurrent_unordered_set.h>
#include "common/concurrent_unordered_common.h"

//! \file test_concurrent_unordered_set.cpp
//! \brief Test for [containers.concurrent_unordered_set containers.concurrent_unordered_multiset] specifications

template <typename... Args>
struct AllowMultimapping<tbb::concurrent_unordered_multiset<Args...>> : std::true_type {};

template <typename Value>
using MyAllocator = LocalCountingAllocator<std::allocator<Value>>;

using move_support_tests::FooWithAssign;

using set_type = tbb::concurrent_unordered_set<int, std::hash<int>, std::equal_to<int>, MyAllocator<int>>;
using multiset_type = tbb::concurrent_unordered_multiset<int, std::hash<int>, std::equal_to<int>, MyAllocator<int>>;
using degenerate_set_type = tbb::concurrent_unordered_set<int, degenerate_hash<int>, std::equal_to<int>, MyAllocator<int>>;
using degenerate_multiset_type = tbb::concurrent_unordered_multiset<int, degenerate_hash<int>, std::equal_


lustreEndShadow
    pathResult.shadowPaths[4].apply {
        if (lustreEndDistance + lustreEndShadowWidth > H.distanceTo(lST)) {
            moveTo(O)
            close()
            return@apply
        }
        moveTo(S2)
        lineTo(T2)
        lineTo(T3)
        lineTo(S3)
        close()
        op(this, thisPageBack, operation = PathOperation.Intersect)
    }

    //lustreStartShadow
    pathResult.shadowPaths[5].apply {
        if (lustreEndDistance + lustreEndShadowWidth > H.distanceTo(lST)) {
            moveTo(O)
            close()
            return@apply
        }
        moveTo(S)
        lineTo(T)
        lineTo(T4)
        lineTo(S4)
        close()
        op(this, thisPageBack, operation = PathOperation.Intersect)
    }

    //求阴影控制点
    val lKL = Line.withKAndOnePoint(lST.k, W)
    val lS1T1 = Line.withKAndOnePoint(lST.k, S1)
    val lHC = Line.withTwoPoints(H, C)

    pathResult.shaderControlPointPairs[0] = Pair(H.avoidNaN(), H2.avoidNaN())
    pathResult.shaderControlPointPairs[1] = Pair(H.avoidNaN(), H1.avoidNaN())
    pathResult.shaderControlPointPairs[2] = Pair(lKL.intersectAt(lHC).avoidNaN(), lS1T1.intersectAt(lHC).avoidNaN())
    pathResult.shaderControlPointPairs[3] = Pair(lS2T2.intersectAt(lHC).avoidNaN(), lS3T3.intersectAt(lHC).avoidNaN())
    pathResult.shaderControlPointPairs[4] = Pair(lST.intersectAt(lHC).avoidNaN(), lS4T4.intersectAt(lHC).avoidNaN())

    pathResult.shadow12Width = shadow12Width
//    return PathResult(
//        listOf(thisPageBack, outline),
//        listOf(shadow1, shadow2, shadow3, shadow4, lustreEndShadow, lustreStartShadow),
//        listOf(
//            Pair(
//                H.avoidNaN(),
//                H2.avoidNaN()
//            ),
//            Pair(
//                H.avoidNaN(),
//                H1.avoidNaN()
//            ),
//            Pair(
//                lKL.intersectAt(lHC).avoidNaN(),
//                lS1T1.intersectAt(lHC).avoidNaN()
//            ),
//            Pair(
//                lS2T2.intersectAt(lHC).avoidNaN(),
//                lS3T3.intersectAt(lHC).avoidNaN()
//            ),
//            Pair(
//                lST.intersectAt(lHC).avoidNaN(),
//                lS4T4.intersectAt(lHC).avoidNaN()
//            )
//        ),
//        shadow12Width
//    )
}

/**
 * 获取Bitmap扭曲后的格点，相对坐标系
 * @return 第一个数组表示扭曲后边界格点[NVJ, ZTN, WSM, MUI]，第二个数组表示扭曲后格点，第三个数组表示扭曲格子数[宽，高]
 */
private fun AllPoints.buildDistortionPoints(
    width: Float,
    height: Float,
    meshWidthCount: Int,
    meshHeightCount: Int,
    isUpsideDown: Boolean
): Pair<Array<List<Float>>, FloatArray> {
    val size = (meshWidthCount + 1) * (meshHeightCount + 1) * 2
    val vertices = FloatArray(size)
    val originalVertices = FloatArray(size)

    val kCH = Line.withTwoPoints(C, H).k
    val lWZ = Line.withKAndOnePoint(-1 / kCH, W)


#include "lsl_common.h"

/* function lsl_push_chunk(LibHandle, Outlet, ChunkData [,Timestamps] [,Pushthrough])
 * - ChunkData must be a MxN double matrix, where each column is a separate sample to push.
 * - Timestamps is a vector of the same length as ChunkData has columns.
 */

void mexFunction( int nlhs, mxArray *plhs[],
		  int nrhs, const mxArray*prhs[] )
{
    /* handle of the desired field */
    mxArray *field, *cell;
    /* temp pointer */
    uintptr_t *pTmp;
    /* function handle */
    lsl_push_sample_dtp_t func_num;   /* numeric data */
    /* input/output variables */
    double *chunkdata, *timestamps;
    int pushthrough=1;
    int k,numsamples,numchannels;
    outlet out;

    if (nrhs < 4)
        mexErrMsgTxt("At least 4 input argument(s) required.");
    if (nrhs > 5)
        mexErrMsgTxt("At most 5 input argument(s) required.");
    if (nlhs != 0)
        mexErrMsgTxt("0 output argument(s) required.");

    /* get function handle */
    field = mxGetField(prhs[0], 0, "lsl_push_sample_dtp");
    if (!field)
        mexErrMsgTxt("The field does not seem to exist.");
    pTmp = (uintptr_t*)mxGetData(field);
    if (!pTmp)
        mexErrMsgTxt("The field seems to be empty.");
    func_num = (lsl_push_sample_dtp_t*)*pTmp;

    /* get outlet ptr */
    out = *(uintptr_t*)mxGetData(prhs[1]);

    /* get ChunkData ptr & check format */
    if (mxGetClassID(prhs[2]) != mxDOUBLE_CLASS)
        mexErrMsgTxt("The ChunkData must be numeric (string-formatted samples must currently be submitted sample-by-sample).");
    chunkdata = (double*)mxGetData(prhs[2]);
    if (mxGetNumberOfElements(prhs[2]) == 0)
        return;
    numchannels = mxGetM(prhs[2]);
    numsamples = mxGetN(prhs[2]);

    /* get timestamp pointer */
    if (mxGetClassID(prhs[3]) != mxDOUBLE_CLASS)
        mexErrMsgTxt("The timestamp argument must be passed as a double.");
    if (mxGetNumberOfElements(prhs[3]) != mxGetN(prhs[2]))
        mexErrMsgTxt("The number of timestamps provided must match the number of columns in the chunk data matrix.");
    timestamps = (double*)mxGetData(prhs[3]);

    if (nrhs >= 5) {
        /* optionally read pushthrough value */
        if (mxGetClassID(prhs[4]) != mxDOUBLE_CLASS)
            mexErrMsgTxt("The pushthrough argument must be passed as a double (1 or 0).");
        pushthrough = ((int)*(double*)mxGetData(prhs[4])) != 0;
    }

    /* now send the samples (pushthrough is only set for the last sample in the chunk) */
    for (k=0;k<numsamples-1;k++,chunkdata+=numchannels,timestamps++)
        func_num(out, chunkdata, *timestamps, 0);
    func_num(out, chunkdata, *timestamps, pushthrough);
}


);
  if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes",
                                          &total)) {
    FAIL("GetNumericProperty failed for generic.current_allocated_bytes");
  }
  if (total < 10) {
    FAIL("GetNumericProperty had bad return for generic.current_allocated_bytes");
  }
  if (!MallocExtension_GetNumericProperty("generic.current_allocated_bytes",
                                          &total)) {
    FAIL("GetNumericProperty failed for generic.current_allocated_bytes");
  }
  MallocExtension_MarkThreadIdle();
  MallocExtension_MarkThreadBusy();
  MallocExtension_ReleaseToSystem(1);
  MallocExtension_ReleaseFreeMemory();
  if (MallocExtension_GetEstimatedAllocatedSize(10) < 10) {
    FAIL("GetEstimatedAllocatedSize returned a bad value (too small)");
  }
  if (MallocExtension_GetAllocatedSize(x) < 10) {
    FAIL("GetEstimatedAllocatedSize returned a bad value (too small)");
  }
  if (MallocExtension_GetOwnership(x) != MallocExtension_kOwned) {
    FAIL("DidAllocatePtr returned a bad value (kNotOwned)");
  }
  /* TODO(csilvers): this relies on undocumented behavior that
     GetOwnership works on stack-allocated variables.  Use a better test. */
  if (MallocExtension_GetOwnership(hist) != MallocExtension_kNotOwned) {
    FAIL("DidAllocatePtr returned a bad value (kOwned)");
  }

  free(x);
}

int main(int argc, char** argv) {
  TestMallocHook();
  TestMallocExtension();

  printf("PASS\n");
  return 0;
}


*/
        opacity: 0.2;
       }
        .AIPodcaste-img,
        .java-img {
          width: 320px;
          height: 300px;
          object-fit: cover;
          object-position: right;
        }
        .java-img,
        .real-estate-img {
          opacity: 0.5;
          width: 380px;
        }
        .real-estate-img {
          width: 320px;
        }
        .project-transform-p,
        .Curriculum-p-tag,
        .Bank-App-p-tag,
        .crude-mern-p-tag,
        .class-repo-p-tag {
          margin-top: -14px;
          /* background-color: ; */
          padding-left: 0;
          width: 70%;
          margin-bottom: 0px;
        }
        .html-css3-tag {
          margin-top: -6px;
          width: 80%;
        }
        .RactNattive-p-tag {
          margin-top: -6px;
          width: 74%;
        }
        .divi-p {
          align-items: center;
        }
        .java-img-div,
        .real-estate-img-div {
          margin-left: 10%;
          bottom: 170px;
          left: -60px;
        }

        .main-6 {
          margin-left: 8%;
        }
        .main-6-child-div {
          height: 340px;
          margin-bottom: 0px;
        }
        .full-stack-p-tag {
          margin-bottom: 0;
        }
        .e-commerce-p-tag {
          margin-top: 10px;
        }
        .js-react-p-tag {
          margin-top: 40px;
        }

        .main-7 {
          margin-top: -30px;
        }
        .hiii-p-div {
          width: 90%;

        }

        .main-8 {
          margin-top: 60px;
          text-align: center;
        }
        .main-8-child {
          display: flex;
          flex-direction: row;
          justify-content: center;
          align-items: center;
          column-gap: 20px;
        }
        .vertical-line-div {
          display: none;
        }
        .main-8-child {
          position: static;
        }
        .main-9 {
          display: none;
        }

     }
  </style>

            01.    About

            02.    Experience

            03.    Work

            04.    Contact


,
		},
		Rules: []rbacv1.PolicyRule{
			{
				APIGroups: []string{""},
				Resources: []string{"persistentvolumeclaims"},
				Verbs:     []string{"get", "list", "watch", "patch", "create", "update", "delete"},
			},
		},
	}
}

// NewClusterRole returns a ClusterRole for managing various K8s and Forklift resources.
func NewClusterRole(roleName string) *rbacv1.ClusterRole {
	return &rbacv1.ClusterRole{
		ObjectMeta: metav1.ObjectMeta{
			Name: roleName,
		},
		Rules: []rbacv1.PolicyRule{
			{
				APIGroups: []string{""},
				Resources: []string{"pods", "persistentvolumeclaims", "persistentvolumes", "storageclasses", "secrets"},
				Verbs:     []string{"get", "list", "watch", "patch", "create", "update", "delete"},
			},
			{
				APIGroups: []string{""},
				Resources: []string{"events"},
				Verbs:     []string{"create", "patch", "update"},
			},
			{
				APIGroups: []string{"storage.k8s.io"},
				Resources: []string{"storageclasses"},
				Verbs:     []string{"get", "list", "watch"},
			},
			{
				APIGroups: []string{"forklift.konveyor.io"},
				Resources: []string{"ovirtvolumepopulators", "vspherexcopyvolumepopulators", "openstackvolumepopulators"},
				Verbs:     []string{"get", "list", "watch", "create", "update", "patch", "delete"},
			},
		},
	}
}

// NewClusterRoleBinding returns a ClusterRoleBinding that binds the SA to the given ClusterRole.
func NewClusterRoleBinding(namespace, roleName, saName string) *rbacv1.ClusterRoleBinding {
	bindingName := fmt.Sprintf("%s-binding", roleName)
	return &rbacv1.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: bindingName,
		},
		Subjects: []rbacv1.Subject{
			{
				Kind:      "ServiceAccount",
				Name:      saName,
				Namespace: namespace,
			},
		},
		RoleRef: rbacv1.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "ClusterRole",
			Name:     roleName,
		},
	}
}

// NewRoleBinding returns a RoleBinding that binds the SA to the Role in the namespace.
func NewRoleBinding(namespace, saName, roleName string) *rbacv1.RoleBinding {
	bindingName := fmt.Sprintf("%s-binding", roleName)
	return &rbacv1.RoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name:      bindingName,
			Namespace: namespace,
		},
		Subjects: []rbacv1.Subject{
			{
				Kind:      "ServiceAccount",
				Name:      saName,
				Namespace: namespace,
			},
		},
		RoleRef: rbacv1.RoleRef{
			APIGroup: "rbac.authorization.k8s.io",
			Kind:     "Role",
			Name:     roleName,
		},
	}
}
package testplan

import (
	"certificate-tool/internal/k8s"
	"certificate-tool/internal/utils"
	"certificate-tool/pkg/vmware"
	"context"
	"fmt"
	"time"

	"k8s.io/client-go/kubernetes"
	"k8s.io/klog/v2"
)

type TestCaseForPrint struct {
	Name    string                `yaml:"name"`
	Success utils.SuccessCriteria `yaml:"success"`
	VMs     []*utils.VM           `yaml:"vms"`
	Results utils.TestResult      `yaml:"results"`
}

// TestCase defines a single test scenario.
type TestCase struct {
	Name                  string                       `yaml:"name"`
	Success


# SPDX-License-Identifier: GPL-2.0-or-later
import subprocess
import sys
import shlex
import os
import re

os.environ["LC_ALL"] = "C"
os.environ["LANG"] = "C"
for k in list(os.environ.keys()):
    if k.startswith("LC_"):
        os.environ.pop(k)

if len(sys.argv) < 2:
    sys.stderr.write("start as format-test.py gcc-123.45 [-options ...]\n")
    sys.exit(1)

c_re = re.compile(r"//\s+(NO)?WARN")
expect = {}
lines = {}

with open("format-test.c", "r") as fd:
    for lno, line in enumerate(fd.readlines(), 1):
        lines[lno] = line.strip()
        m = c_re.search(line)
        if m is None:
            continue
        if m.group(1) is None:
            expect[lno] = "warn"
        else:
            expect[lno] = "nowarn"

cmd = shlex.split(
    "-Wall -Wextra -Wno-unused -fplugin=./frr-format.so -fno-diagnostics-show-caret -c -o format-test.o format-test.c"
)

gcc = subprocess.Popen(
    sys.argv[1:] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
sout, serr = gcc.communicate()
gcc.wait()

gcclines = serr.decode("UTF-8").splitlines()
line_re = re.compile(r"^format-test\.c:(\d+):(.*)$")
gcc_warns = {}

for line in gcclines:
    if line.find("In function") >= 0:
        continue
    m = line_re.match(line)
    if m is None:
        sys.stderr.write("cannot process GCC output: %s\n" % line)
        continue

    lno = int(m.group(1))
    gcc_warns.setdefault(lno, []).append(line)

for lno, val in expect.items():
    if val == "nowarn" and lno in gcc_warns:
        sys.stderr.write(
            "unexpected gcc warning on line %d:\n\t%s\n\t%s\n"
            % (lno, lines[lno], "\n\t".join(gcc_warns[lno]))
        )
    if val == "warn" and lno not in gcc_warns:
        sys.stderr.write(
            "expected warning on line %d but did not get one\n\t%s\n"
            % (lno, lines[lno])
        )

leftover = set(gcc_warns.keys()) - set(expect.keys())
for lno in sorted(leftover):
    sys.stderr.write(
        "unmarked gcc warning on line %d:\n\t%s\n\t%s\n"
        % (lno, lines[lno], "\n\t".join(gcc_warns[lno]))
    )


({type:a}));
!d&&B&&(d=a&&c.ok()?!!(8<l&&a.match(kb)||a.match(c.mimePattern)):null);return d};this.canPlayURL=function(a){var d;c.hasHTML5&&(d=Z({url:a}));!d&&B&&(d=a&&c.ok()?!!a.match(c.filePattern):null);return d};this.canPlayLink=function(a){return a.type!==g&&a.type&&c.canPlayMIME(a.type)?!0:c.canPlayURL(a.href)};this.getSoundById=function(a,d){if(!a)throw Error("soundManager.getSoundById(): sID is null/_undefined");var e=c.sounds[a];!e&&!d&&c._wD('"'+a+'" is an invalid sound ID.',2);return e};this.onready=
function(a,d){if("function"===typeof a)n&&c._wD(p("queue","onready")),d||(d=j),ua("onready",a,d),I();else throw p("needFunction","onready");return!0};this.ontimeout=function(a,d){if("function"===typeof a)n&&c._wD(p("queue","ontimeout")),d||(d=j),ua("ontimeout",a,d),I({type:"ontimeout"});else throw p("needFunction","ontimeout");return!0};this._writeDebug=function(a,d){var e,b;if(!c.debugMode)return!1;if(gb&&c.useConsole){if(d&&"object"===typeof d)console.log(a,d);else if(Ua[d]!==g)console[Ua[d]](a);
else console.log(a);if(c.consoleOnly)return!0}e=A("soundmanager-debug");if(!e)return!1;b=h.createElement("div");0===++qb%2&&(b.className="sm2-alt");d=d===g?0:parseInt(d,10);b.appendChild(h.createTextNode(a));d&&(2<=d&&(b.style.fontWeight="bold"),3===d&&(b.style.color="#ff3333"));e.insertBefore(b,e.firstChild);return!0};-1!==R.indexOf("sm2-debug=alert")&&(this._writeDebug=function(c){j.alert(c)});this._wD=this._writeDebug;this._debug=function(){var a,d;k("currentObj",1);a=0;for(d=c.soundIDs.length;a<
d;a++)c.sounds[c.soundIDs[a]]._debug()};this.reboot=function(a,d){c.soundIDs.length&&c._wD("Destroying "+c.soundIDs.length+" SMSound objects...");var e,b,f;for(e=c.soundIDs.length-1;0<=e;e--)c.sounds[c.soundIDs[e]].destruct();if(i)try{H&&(Aa=i.innerHTML),W=i.parentNode.removeChild(i),k("flRemoved")}catch(g){k("badRemove",2)}Aa=W=B=i=null;c.enabled=V=n=X=Ca=S=T=r=D=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};if(a)C=[];else for(e in C)if(C.hasOwnProperty(e)){b=0;for(f=C[e].length;b<f;b++)C[e][b].fired=
!1}d||c._wD("soundManager: Rebooting...");c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;j.setTimeout(function()


key.get_content(),
        method = "PUT",
        headers = { ["Content-Type"] = "application/json" },
        body = body,
    })

    print(res)

    if res and res.status then
        if res.status == 429 then
            result.set_content("Failed due to ratelimit.")
        elseif res.status == 404 then
            result.set_content("Failed due to: domain not found.")
        elseif res.status == 400 then
            result.set_content("Failed due to: invalid body.\nMake sure all fields are completed")
        elseif res.status == 200 then
            result.set_content("Success!")
        else
            result.set_content("Failed due to error: " .. res.status)
        end
    elseif res and res.ip then
        result.set_content("Success!")
    else
        result.set_content("Failed due to unknown error.")
    end
end)

delete_done.on_click(function()
    local res = fetch({
        url = "https://api.buss.lol/domain/" .. delete_key.get_content(),
        method = "DELETE",
        headers = { ["Content-Type"] = "application/json" },
    })

    print(res)

    if res and res.status then
        if res.status == 429 then
            result.set_content("Failed due to ratelimit.")
        elseif res.status == 404 then
            result.set_content("Failed due to: domain not found.")
        elseif res.status == 200 then
            result.set_content("Success!")
        else
            result.set_content("Failed due to error: " .. res.status)
        end
    elseif res and res.secret_key then
        result.set_content("Success!")
    else
        result.set_content("Failed due to unknown error.")
    end
end)


 = false;
//					String commentFree = "";
//					String lineTail = trimmedLine;
//					while (!lineTail.isEmpty() && !commentsChecked) {
//						if (inComment) {
//							// check if the line ends the current comment block
//							int commentPos = lineTail.indexOf("*/");
//							if (commentPos >= 0) {
//								inComment = false;
//								commentPos += 2;
//								if (lineTail.length() > commentPos) {
//									lineTail = " " + lineTail.substring(commentPos).trim();
//								} else {
//									lineTail = "";
//								}
//							}
//							else {
//								commentsChecked = true;
//								lineTail = "";
//							}
//						}
//
//						if (!inComment && !lineTail.isEmpty()) {
//							// remove inline comments
//							int commentPos = lineTail.indexOf("//");
//							if (commentPos > 0) {
//								lineTail = lineTail.substring(0, commentPos).trim();
//							}
//							// check if the line starts a new comment block
//							commentPos = lineTail.indexOf("/*");
//							if (commentPos >= 0) {
//								inComment = true;
//								if (commentPos > 0) {
//									commentFree += " " + lineTail.substring(0, commentPos).trim();
//								}
//								commentPos += 2;
//								if (lineTail.length() > commentPos) {
//									lineTail = lineTail.substring(commentPos);
//								} else {
//									lineTail = "";
//								}
//							}
//							else {
//								commentsChecked = true;
//							}
//						}
//
//					}
//					trimmedLine = (commentFree + lineTail).trim();
					String[] arg = {trimmedLine};
					inComment = checkComments(arg, inComment);
					trimmedLine = arg[0];
					// END KGU#582 2018-09-25

					// Note: trimmedLine can be empty if we start a block comment only
					if (trimmedLine.isEmpty()) {
						if (_srcCodeSB != null) {
							// no processing if we only want to check for defines
							_srcCodeSB.append(strLine);
							_srcCodeSB.append("\n");
							// START KGU#1075 2023-09-12: Bugfix #1085 typedef scopes were mixed
							lineNo++;
							// END KGU#1075 2023-09-12
						}
						continue;
					}
					// FIXME: try to take care for #if/#else/#endif, maybe depending upon an import setting
					//        likely only useful if we parse includes...
					//        and/or add a standard (dialect specific) list of defines
					if (trimmedLine.charAt(0) == '#') {
						if (_srcCodeSB == null) {
							// START KGU#1075 2023-09-12: Bugfix #1085 - We must handle recursive ranges
							//handlePreprocessorLine(trimmedLine.substring(1), defines);
							// START KGU#1105 2023-11-13: Enh. #1115 Care for constant conversions
							//handlePreprocessorLine(trimmedLine.substring(1), defines, lineNo);
							handlePreprocessorLine(trimmedLine.substring(1), defines, lineNo, _textToParse);
							// END KGU#1105 2023-11-13
							// END KGU#1075 2023-09-12
							// no further processing if we only want to check for defines
							continue;
						}
						// START KGU#582 2018-09-25: Bugfix #608 (makeshift approach)
						// There are cases where within the preprocessor line a multi-line comment starts
						// with "/*" (i.e. with the "*/" not following in the very line!).
						// In these cases the prefix "// preparser ..." will cause syntax errors on end,
						// because the ne


 with message type could contain
  // required fields, so we have to be conservative and assume such an
  // extension exists.
  if (type->extension_range_count() > 0) return true;

  for (int i = 0; i < type->field_count(); i++) {
    const FieldDescriptor* field = type->field(i);
    if (field->is_required()) {
      return true;
    }
    if (GetJavaType(field) == JAVATYPE_MESSAGE) {
      if (HasRequiredFields(field->message_type(), already_seen)) {
        return true;
      }
    }
  }

  return false;
}

static bool HasRequiredFields(const Descriptor* type) {
  hash_set<const Descriptor*> already_seen;
  return HasRequiredFields(type, &already_seen);
}

}  // namespace

// ===================================================================

MessageGenerator::MessageGenerator(const Descriptor* descriptor)
  : descriptor_(descriptor),
    field_generators_(descriptor) {
}

MessageGenerator::~MessageGenerator() {}

void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
  if (HasDescriptorMethods(descriptor_)) {
    // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
    // used in the construction of descriptors, we have a tricky bootstrapping
    // problem.  To help control static initialization order, we make sure all
    // descriptors and other static data that depends on them are members of
    // the outermost class in the file.  This way, they will be initialized in
    // a deterministic order.

    map<string, string> vars;
    vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
    vars["index"] = SimpleItoa(descriptor_->index());
    vars["classname"] = ClassName(descriptor_);
    if (descriptor_->containing_type() != NULL) {
      vars["parent"] = UniqueFileScopeIdentifier(
          descriptor_->containing_type());
    }
    if (descriptor_->file()->options().java_multiple_files()) {
      // We can only make these package-private since the classes that use them
      // are in separate files.
      vars["private"] = "";
    } else {
      vars["private"] = "private ";
    }

    // The descriptor for this type.
    printer->Print(vars,
      "$private$static com.google.protobuf.Descriptors.Descriptor\n"
      "  internal_$identifier$_descriptor;\n");

    // And the FieldAccessorTable.
    printer->Print(vars,
      "$private$static\n"
      "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
      "    internal_$identifier$_fieldAccessorTable;\n");
  }

  // Generate static members for all nested types.
  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
    // TODO(kenton):  Reuse MessageGenerator objects?
    MessageGenerator(descriptor_->nested_type(i))
      .GenerateStaticVariables(printer);
  }
}

void MessageGenerator::GenerateStaticVariableInitializers(
    io::Printer* printer) {
  if (HasDescriptorMethods(descriptor_)) {
    map<string, string> vars;
    vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
    vars["index"] = SimpleItoa(descriptor_->index());
    vars["classname"] = ClassName(descriptor_);
    if (descriptor_->containing_type() != NULL) {
      vars["parent"] = UniqueFileScopeIdentifier(
          descriptor_->containing_type());
    }

    // The descriptor for this type.
    if (descriptor_->containing_type() == NULL) {
      printer->Print(vars,
        "internal_$identifier$_descriptor =\n"
        "  getDescriptor().getMessageTypes().get($index$);\n");
    } else {
      printer->Print(vars,
        "internal_$identifier$_descriptor =\n"
        "  internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
    }

    // And th


anguage.Add(i .. "_ammo", PLUGIN:GetPhrase("ammo." .. i) or i)
	end
end

if CLIENT then
	hook.Add("InitPostEntity", "tacrp_hl2hud", function()
		if not HL2HUD then return end
		local tbl = HL2HUD.scheme.GetDefault().HudTextures.AmmoInv
		local tbl2 = HL2HUD.scheme.GetDefault().HudTextures.Ammo

		for k, v in pairs(materials) do
			local info = {
				type = 2,
				w = 64,
				h = 64,
				x = 0,
				y = 0,
				u1 = 0,
				u2 = 64,
				v1 = 0,
				v2 = 64,
				scalable = false,
				texture = surface.GetTextureID(v)
			}
			if not tbl[k] then
				tbl[k] = info
			end
			if not tbl2[k] then
				tbl2[k] = info
			end
		end
	end)
end


(String titleInput, String content) async {
    try {
      // 获取临时目录
      final tempDir = await getTemporaryDirectory();
      String title = titleInput.trim();
      // 如果用户未输入标题，则自动从内容第一行生成
      if (title.isEmpty) {
        title = content
            .trim()
            .split('\n')
            .firstWhere((l) => l.trim().isNotEmpty, orElse: () => '无标题文本')
            .trim();
        if (title.length > 40) {
          title = title.substring(0, 40);
        }
      }

      // 清理文件名中的非法字符
      final sanitizedTitle = title.replaceAll(RegExp(r'[\/:*?"<>|]'), '_');
      final uniqueId = const Uuid().v4().substring(0, 8); // 添加唯一ID防止重名
      final fileName = '$sanitizedTitle-$uniqueId.txt';
      final filePath = p.join(tempDir.path, fileName);

      // 将内容写入临时文件
      final file = File(filePath);
      await file.writeAsString(content);

      // 调用标准的文件处理流程
      await _processFiles([filePath]);
    } catch (e, s) {
      LogService.instance.error('粘贴导入失败', e, s);
      if (mounted) {
        _showTopMessage('粘贴导入失败: $e', isError: true);
      }
    }
  }

  /// START: 功能函数未改变，保持原样 ///
  void _showAiNovelCreationFlow() async {
    // 导航到新的、独立的AI创作流程入口页面
    await Navigator.of(context).push<bool>(
      MaterialPageRoute(
        builder: (context) => const AiGenerateOutlinePage(),
      ),
    );

    // 当创作完成并从编辑页面返回时，无论成功与否都刷新书架
    // 这样确保任何情况下书架都是最新的
    await _loadBookshelf();
  }

  /// 为指定书籍生成插图任务
  Future<void> _generateIllustrations(BookshelfEntry entry) async {
    // 显示配置对话框，并等待其返回结果
    final bool? taskCreated = await showDialog<bool>(
      context: context,
      barrierDismissible: false,
      builder: (context) => GenerateIllustrationDialog(entry: entry),
    );

    // 如果对话框返回true，说明任务已成功创建
    if (taskCreated == true && mounted) {
      // 重新从缓存加载书架数据，以更新UI状态（例如显示"排队中"）
      await _loadBookshelf();

      // 找到更新后的条目，以获取正确的任务信息用于提示
      final updatedEntry = _entries.firstWhere(
        (e) => e.id == entry.id,
        orElse: () => entry,
      );

      ScaffoldMessenger.of(context).hideCurrentSnackBar();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('已为《${updatedEntry.title}》创建 ${updatedEntry.taskChunks.length} 个生成子任务'),
        ),
      );
    }
  }

  /// 为指定书籍生成翻译任务
  Future<void> _generateTranslations(BookshelfEntry entry) async {
    // 显示配置对话框，并等待其返回结果
    final bool? taskCreated = await showDialog<bool>(
      context: context,
      barrierDismissible: false,
      builder: (context) => GenerateTranslationDialog(entry: entry),
    );

    // 如果对话框返回true，说明任务已成功创建
    if (taskCreated == true && mounted) {
      // 重新从缓存加载书架数据，以更新